使用 GNU sed ,我尝试替换文件中第一个出现的模式,但是如果比赛之前还有其他模式,我不想替换。
例如,如果文件包含带有“ bird [number]”的行,则在此模式之前任何地方都没有“ cat”一词的情况下,我想将数字替换为“ 0”。
示例文字
dog cat - fish bird 123
dog fish - bird 1234567
dog - cat fish, lion bird 3456
预期结果:
dog cat - fish bird 123
dog fish - bird 0
dog - cat fish, lion bird 3456
我尝试结合How to use sed to replace only the first occurrence in a file?和Sed regex and substring negation解决方案,并提出类似的建议
sed -E '0,/cat.*bird +[0-9]+/b;/(bird +)[0-9]+/ s//\10/'
如果0,/cat.*bird +[0-9]+/b;/(bird +)[0-9]+/
模式不匹配,但是(bird +)[0-9]+
应该与cat.*bird +[0-9]+
的第一次出现相匹配,但是我得到了
dog cat - fish bird 123
dog fish - bird 0
dog - cat fish, lion bird 0
第三行也被更改。我该如何预防?我认为这与地址范围有关,但我不知道如何取反地址范围的第二部分。
答案 0 :(得分:1)
这可能对您有用(GNU sed):
sed '/\<cat\>.*\<bird\>/b;s/\<\(bird\) \+[0-9]\+/\1 0/;T;:a;n;ba' file
如果一行cat
之前包含一个单词bird
,则对该行结束处理。
尝试将单词bird
之后的数字替换为零。如果未成功,则结束该行的处理。否则,请读取/打印以下所有行,直到文件末尾。
也可能写成:
sed -E '/cat.*bird/b;/(bird +)[0-9]+/{s//\10/;:a;n;ba}' file
答案 1 :(得分:0)
sed用于简单的s / old / new替换,仅此而已。对于其他任何事情,只需使用awk,例如使用GNU awk而不是您正在使用的GNU sed:
$ awk 'match($0,/(.*bird\s+)[0-9]+(.*)/,a) && (a[1] !~ /cat/) {$0=a[1] 0 a[2]} 1' file
dog cat - fish bird 123
dog fish - bird 0
dog - cat fish, lion bird 3456