我想搜索并替换一个简单的字符串,仅在每行上有这么多匹配后开始,例如:
s / ZZ / YY,n = 2
xxxZZxxxxxxZZxxxxZZxZZxxxxZZ
xZZxxxZZxxZZxxZZxZZxxxZZxxx
...
成:
xxxZZxxxxxxZZxxxxxYYxxxxYY
xZZxxxZZxxYYxxYYxYYxxxYYxxx
...
在我的问题中,在连续的“ZZ”之间总会有一个'x'。提前谢谢。
答案 0 :(得分:4)
我建议使用可执行的替换字符串,它允许您计算到目前为止看到的匹配数
此代码演示
use strict;
use warnings;
while (<DATA>) {
my $n = 0;
s/(ZZ)/$n++ < 2 ? $1 : 'YY'/eg;
print;
}
__DATA__
xxxZZxxxxxxZZxxxxZZxZZxxxxZZ
xZZxxxZZxxZZxxZZxZZxxxZZxxx
<强>输出强>
xxxZZxxxxxxZZxxxxYYxYYxxxxYY
xZZxxxZZxxYYxxYYxYYxxxYYxxx
答案 1 :(得分:3)
可能有后备解决方案,或者反向串行和反向前进和反向再次解决方案(如果有的话,我会支持它们),但我通常会发现使用while
的解决方案更容易发现,并且更容易阅读。
1 while $string =~ s/(ZZ.*ZZ.*)ZZ/$1YY/
也就是说,虽然字符串包含三个ZZ
模式,但请将第三个模式替换为YY
。
作为一般解决方案:
$expr = (quotemeta($pattern1) . ".*") x $n;
1 while $string =~ s/($expr)\Q$pattern2\E/$1$pattern2/;
答案 2 :(得分:1)
似乎最简单的perl解决方案应:1 while s/ZZ/YY/3
,但perl不接受。对sed
:
sed ':a
s/ZZ/YY/3
ta'
sed
的某些实现允许更简单地编写:sed ':a; s/ZZ/YY/3; ta'
,并且我相信它可以完全移植:sed -e :a -e s/ZZ/YY/3 -e ta
答案 3 :(得分:1)
1 while $thisline=~s/((?:x*?ZZx*?){2}[xZY]*?)ZZ/$1YY/;
这是n = 2的解决方案。
您只需更改其他n值的数字。
此外,我使用延迟匹配优化了替换,并消除了多余的捕获。