英文:
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并保存整个文件。
非常感谢
英文:
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
答案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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论