awk/sed 从那一点开始查找,然后再次查找。

huangapple go评论79阅读模式
英文:

awk/sed find then find again from that point

问题

Sure, here's the translation of your provided text:

我有一个文件,我想要查找并替换一个非常具体的行。我提供了一个简化的文件示例,我将其称为test.in。如果我要手动执行此操作,我会先查找“log 3”,然后从那一点开始查找“old string”,并将其替换为“new string”。实际上,文件很大,在LOG号和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

但这也不起作用,因为它假设我在到达需要替换的位置之前知道有多少个“old string”,而在实际情况下,由于有许多不同的文件,我不知道。

不能简单地查找LOG 3并带有一行空格的old string然后替换,因为LOG 3和old string之间有大量不同的信息。

有没有一种简单的方法可以查找某些内容,然后从新位置再次搜索,然后使用sed/awk并保存整个文件。

非常感谢 awk/sed 从那一点开始查找,然后再次查找。

英文:

I have a file where I want to find and replace a very specific line. I have provided a simplified file below which I'll call test.in. If I were to do this manually I would find "log 3" then I would find "old string" from that point and replace it with "new string". In practice the files are large with lots of information between LOG number and old string, but these are the unique identifiers.

*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

I thought about using the following:

  grep -A 700 "*LOG 3" test.in | sed '0,/old string/{s/old string/new string/}'

But this doesn't work for me as I need to correct the entire file. I also came across the following on these pages:

awk '/old string/{count++;if(count==3){sub("old string","new string")}}1' test.in

However this also doesn't work as it assumes I know how many "old string" there are before I get to the one I need to replace - and in practice I don't as there are many different files.

I cannot simply find LOG 3 with a line space and old string and replace it that way, as there is a ton of different information between LOG 3 and old string.

Is there a simple way I can find something then search again from that new position, and then use sed/awk and save the entire file.

Many thanks awk/sed 从那一点开始查找,然后再次查找。

答案1

得分: 4

Translated:

> *LOG 3包含 *old string* 的下一行,将 old string 替换为 new string

英文:

Simply 1 sed line

sed '/^\*LOG 3/,/old string/s/old string/new string/' test.in

Translated:

> From *LOG 3 to next line containing *old string*, replace old string by new string

答案2

得分: 3

使用awk,你可以像F. Hauri的sed解决方案中所做的一样执行相同的操作:

然而,如果你想要开始在awk中执行其他操作,这种方法不够灵活。因此,使用标志方法是最简单的:

英文:

With awk you could do the same as in the (sed solution from F. Hauri](https://stackoverflow.com/a/59582010/8344060)

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

This is, however, not really flexible if you want to start doing other things with your awk. The flag method is, therefore, the easiest:

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

答案3

得分: 1

这可能是你想要的:

$ 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 [想要替换为 "new string"]

*LOG 4

old string
old string

请注意,尽管你要搜索和替换的文本中包含单词 "string",但上面的awk解决方案以及到目前为止发布的任何sed解决方案或其他awk解决方案都不是进行字面字符串搜索和替换。相反,它们搜索正则表达式并用启用反向引用的字符串进行替换,因此在处理各种元字符时可能会出现问题。如果你真的想要进行字面字符串搜索和替换,那么可以使用以下方法:

$ 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 [想要替换为 "new string"]

*LOG 4

old string
old string
英文:

This is probably what you want:

$ 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

Note that although the text you're searching for and replacing has the word "string" in it, the above and any sed solution or any other awk solution posted so far is NOT doing a literal string search/replace. Instead it's searching for a regexp and replacing it with a backreference-enabled string so it'll misbehave given various metacharacters. If you REALLY want to do a literal string search/replace then it's:

$ 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

答案4

得分: 0

不确定如何在sed中完成这个操作,但在vim中(ex/vi也可以?),您可以简单地将正则表达式一个接一个地粘贴:

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

Not sure how it's done with sed, but with vim (ex/vi too?) you can simply paste regexps one after another:

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

huangapple
  • 本文由 发表于 2020年1月3日 23:57:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/59581589.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定