awk/sed查找然后从该点再次查找

awk/sed查找然后从该点再次查找,awk,sed,Awk,Sed,我有一个文件,我想找到并替换一个非常具体的行。我提供了一个简化文件,下面我将调用test.in。如果手动执行此操作,我将查找日志3,然后从该点查找旧字符串并用新字符串替换它。实际上,文件很大,日志号和旧字符串之间有很多信息,但这些是唯一的标识符 *LOG 1 old string old string *LOG 2 old string old string old string *LOG 3 old string [Want to replace this with "new str

我有一个文件,我想找到并替换一个非常具体的行。我提供了一个简化文件,下面我将调用test.in。如果手动执行此操作,我将查找日志3,然后从该点查找旧字符串并用新字符串替换它。实际上,文件很大,日志号和旧字符串之间有很多信息,但这些是唯一的标识符

*LOG 1

old string
old string

*LOG 2

old string
old string
old string

*LOG 3

old string [Want to replace this with "new string"]


*LOG 4

old string
old string
我考虑使用以下方法:

  grep -A 700 "*LOG 3" test.in | sed '0,/old string/{s/old string/new string/}'
但这对我不起作用,因为我需要更正整个文件。在这些页面上,我还发现了以下内容:

awk '/old string/{count++;if(count==3){sub("old string","new string")}}1' test.in
然而,这也不起作用,因为它假设我在找到需要替换的字符串之前知道有多少个旧字符串——实际上我不知道,因为有很多不同的文件

我不能简单地找到带有行空间和旧字符串的日志3并用这种方式替换它,因为日志3和旧字符串之间有大量不同的信息

有没有一种简单的方法可以让我找到一些东西,然后从新位置再次搜索,然后使用sed/awk保存整个文件


非常感谢:

不知道如何使用sed,但也可以使用vim ex/vi?您只需逐个粘贴regexp即可:

vim '+/^\*LOG 3//^old string/s/.*/new string' '+wq' test.txt

不确定sed是如何实现的,但vim ex/vi也是如此?您只需逐个粘贴regexp即可:

vim '+/^\*LOG 3//^old string/s/.*/new string' '+wq' test.txt
简单1 sed行 翻译成:

从*日志3到包含*旧字符串*的下一行,用新字符串替换旧字符串

简单1 sed行 翻译成:

从*日志3到包含*旧字符串*的下一行,用新字符串替换旧字符串

使用awk,您可以执行与F.Hauri的sed解决方案相同的操作]

然而,如果你想开始用awk做其他事情,这并不是很灵活。因此,flag方法是最简单的:

awk '/^[*]LOG 3$/{f=1};f{f=!(sub(/old_string/,"new_string"))}; 1' file
使用awk,您可以执行与F.Hauri的sed解决方案相同的操作]

然而,如果你想开始用awk做其他事情,这并不是很灵活。因此,flag方法是最简单的:

awk '/^[*]LOG 3$/{f=1};f{f=!(sub(/old_string/,"new_string"))}; 1' file

这可能是您想要的:

$ awk '/^\*LOG/{f=($NF==3)} f{sub(/old string/,"new string")} 1' file
*LOG 1

old string
old string

*LOG 2

old string
old string
old string

*LOG 3

new string [Want to replace this with "new string"]


*LOG 4

old string
old string
请注意,尽管您正在搜索和替换的文本中包含单词字符串,但上述和任何sed解决方案或任何其他发布的awk解决方案都没有执行文字字符串搜索/替换。相反,它搜索一个regexp,并将其替换为一个支持反向引用的字符串,这样在给定各种元字符的情况下,它就会出现错误行为。如果您真的想执行文字字符串搜索/替换,那么:

$ awk '
    BEGIN { old="old string"; new="new string" }
    /^\*LOG/ { f=($NF==3) }
    f && s=index($0,old) { $0=substr($0,1,s-1) new substr($0,s+length(old)) }
1' file
*LOG 1

old string
old string

*LOG 2

old string
old string
old string

*LOG 3

new string [Want to replace this with "new string"]


*LOG 4

old string
old string

这可能是您想要的:

$ awk '/^\*LOG/{f=($NF==3)} f{sub(/old string/,"new string")} 1' file
*LOG 1

old string
old string

*LOG 2

old string
old string
old string

*LOG 3

new string [Want to replace this with "new string"]


*LOG 4

old string
old string
请注意,尽管您正在搜索和替换的文本中包含单词字符串,但上述和任何sed解决方案或任何其他发布的awk解决方案都没有执行文字字符串搜索/替换。相反,它搜索一个regexp,并将其替换为一个支持反向引用的字符串,这样在给定各种元字符的情况下,它就会出现错误行为。如果您真的想执行文字字符串搜索/替换,那么:

$ awk '
    BEGIN { old="old string"; new="new string" }
    /^\*LOG/ { f=($NF==3) }
    f && s=index($0,old) { $0=substr($0,1,s-1) new substr($0,s+length(old)) }
1' file
*LOG 1

old string
old string

*LOG 2

old string
old string
old string

*LOG 3

new string [Want to replace this with "new string"]


*LOG 4

old string
old string

是否只对*log3和*log4之间的第一个旧字符串执行操作,或者假设可以有多个旧字符串?是否只对*log3和*log4之间的第一个旧字符串执行操作,或者假设可以有多个旧字符串执行操作?