0

我想搜索和替换一个简单的字符串,仅在每行有这么多匹配之后才开始,例如:

n=2 的 s/ZZ/YY

xxxZZxxxxxxZZxxxxZZxZZxxxxZZ
xZZxxxZZxxZZxxZZxZZxxxZZxxx
...

进入:

xxxZZxxxxxxZZxxxxxYYxxxxYY
xZZxxxZZxxYYxxYYxYYxxxYYxxx
...

在我的问题中,连续的“ZZ”之间总会有一个“x”。提前致谢。

4

4 回答 4

4

我建议一个可执行的替换字符串,它可以让你计算到目前为止看到的匹配数

这段代码演示

use strict;
use warnings;

while (<DATA>) {
  my $n = 0;
  s/(ZZ)/$n++ < 2 ? $1 : 'YY'/eg;
  print;
}

__DATA__
xxxZZxxxxxxZZxxxxZZxZZxxxxZZ
xZZxxxZZxxZZxxZZxZZxxxZZxxx

输出

xxxZZxxxxxxZZxxxxYYxYYxxxxYY
xZZxxxZZxxYYxxYYxYYxxxYYxxx
于 2012-09-18T21:15:08.337 回答
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/;
于 2012-09-18T20:57:32.960 回答
1

It seems like the simplest perl solution should be: 1 while s/ZZ/YY/3, but perl does not accept that. So do the same with sed:

sed ':a
  s/ZZ/YY/3
  ta'

Some implementations of sed allow this to be written more simply: sed ':a; s/ZZ/YY/3; ta', and I believe it is fully portable to write: sed -e :a -e s/ZZ/YY/3 -e ta

于 2012-09-18T21:25:49.067 回答
1
1 while $thisline=~s/((?:x*?ZZx*?){2}[xZY]*?)ZZ/$1YY/;

That is a solution for n=2.

You can just change the number there for other values of n.

Also, I optimized the substitution with lazy matching and by doing away with superfluous capturing.

于 2012-09-19T13:46:17.557 回答