如何在BASH中查找并替换匹配的每个偶数编号外观?

时间:2013-11-28 07:40:32

标签: perl bash replace sed awk

我正在使用sed -i 's/AAA/ZZZ/g' filename在文件中用“ZZZ”替换每个“AAA”的出现。我需要用“ZZZ”替换每个偶数编号的“AAA”外观,例如:

This is a AAA sentence. AAA
This is another AAA sentence.
This is yet AAA another AAA sentence.
This is AAA stillAAA AAA yet AAA another AAA sentence.

这将成为:

This is a AAA sentence. ZZZ
This is another AAA sentence.
This is yet ZZZ another AAA sentence.
This is ZZZ stillAAA ZZZ yet AAA another ZZZ sentence.

如何更换匹配的每个偶数编号外观?

7 个答案:

答案 0 :(得分:4)

awk是比sed更好的工具。考虑一下这个awk命令:

awk -F 'AAA' '{for (i=1; i<NF; i++) {OFS=c%2?"ZZZ":FS; printf "%s%s", $i, OFS; c++}
    print $NF}' file
This is a AAA sentence. ZZZ
This is another AAA sentence.
This is yet ZZZ another AAA sentence.
This is ZZZ stillAAA ZZZ yet AAA another ZZZ sentence.

此awk将输入字段分隔符设置为AAA,并在AAAZZZ之间切换输出字段分隔符,具体取决于计数器是奇数还是偶数。每次计数器均为OFS时设置为AAA,当奇数时OFS设置为ZZZ

答案 1 :(得分:4)

这是一个简短的gnu awk版本

awk '{ORS=NR%2==0?"ZZZ":RS}1' RS="AAA" file
This is a AAA sentence. ZZZ
This is another AAA sentence.
This is yet ZZZ another AAA sentence.
This is ZZZ stillAAA ZZZ yet AAA another ZZZ sentence.

答案 2 :(得分:2)

这是一个perl解决方案:

$ cat inp
This is a AAA sentence. AAA
This is another AAA sentence.
This is yet AAA another AAA sentence.
This is AAA stillAAA AAA yet AAA another AAA sentence.

$ perl -pe 'my $line = "" ; while(<>){ $line=$line.$_} $line =~ s/(.*?AAA.*?)AAA/\1ZZZ/mgs; print $line;' < inp
This is another AAA sentence.
This is yet ZZZ another AAA sentence.
This is ZZZ stillAAA ZZZ yet AAA another ZZZ sentence.

在这里,首先我将整个文件累积在变量$line中。 &安培;然后,我用ZZZ替换每个交替出现的AAA;使用非贪婪匹配。

答案 3 :(得分:2)

的Perl:

perl -wpe 'BEGIN{$/="AAA"} $.%2 or s/AAA/ZZZ/' foo.txt

答案 4 :(得分:1)

您也可以使用sed执行此操作:

sed -n -e '1,$ { 
:oddline  s/AAA/\n/g; :odd  s/\n/AAA/m; t even ;p;N;s/.*\n//;b oddline ; 
:evenline s/AAA/\n/g; :even s/\n/ZZZ/m; t odd ; p;N;s/.*\n//;b evenline ; 
}' << _END_
This is a AAA sentence. AAA
This is another AAA sentence.
This is yet AAA another AAA sentence.
This is AAA stillAAA AAA yet AAA another AAA sentence.
_END_

sed脚本遍历所有行并记住奇数/偶数替换(跨行)。在模式空间中,所有AAA首先被换行替换,然后由AAA或ZZZ一次替换一个。为了切换到下一行,首先添加(N),然后删除前一行(s/.*\n//)。

答案 5 :(得分:1)

这可能适合你(GNU sed):

sed -r ':a;$!{N;ba};/\x00/q1;s/AAA/\x00/g;s/(\x00)([^\x00]*)\1/AAA\2ZZZ/g' file

将文件存入内存,然后用唯一字符替换AAA的所有出现。然后,每个奇数甚至出现的唯一字符分别被AAAZZZ替换。

N.B。如果unique character不唯一,则不会对文件进行任何更改,并设置错误代码1

第二种方法更加冗长,但可用于更改N'值,而不依赖于unique value

sed  -r 's/AAA/\n&/g;/\n/!b;G;:a;s/$/#/;s/#{2}$//;/\n$/s/\nAAA/\nZZZ/;s/\n//;/\n.*\n/ba;P;s/^.*\n//;h;d' file

它存储保留空间中所需模式的出现次数,并在遇到具有这种模式的行时检索它。

答案 6 :(得分:1)

sed "1 h;1 !H;$ {x;l;s/=/=e/g;s/²/=c/g;s/AAA/²/g;s/²\([^²]\{1,\}\)²/²\1ZZZ/g;s/²/AAA/g;s/=c/²/g;s/=e/=/g;}" YourFile

使用替换(由于AAA可能位于。*内),即使使用替换字符在内部也可以使用前后双重翻译