在Perl中,如何编写一个正则表达式,每个字符串最多只能替换N个匹配项?
也就是说,我正在寻找s/aa/bb/;和之间的中间地带s/aa/bb/g;.我想允许多次替换,但最多只允许N次.
我可以想到三种可靠的方法.第一种是在第N次与自身匹配后替换所有内容.
my $max = 5;
$s =~ s/(aa)/ $max-- > 0 ? 'bb' : $1 /eg;
Run Code Online (Sandbox Code Playgroud)
如果有超过N个匹配,则效率不高.为此,我们需要将循环移出正则表达式引擎.接下来的两种方法是这样做的方法.
my $max = 5;
my $out = '';
$out .= $1 . 'bb' while $max-- && $in =~ /\G(.*?)aa/gcs;
$out .= $1 if $in =~ /\G(.*)/gcs;
Run Code Online (Sandbox Code Playgroud)
这次,就地:
my $max = 5;
my $replace = 'bb';
while ($max-- && $s =~ s/\G.*?\Kaa/$replace/s) {
pos($s) = $-[0] + length($replace);
}
Run Code Online (Sandbox Code Playgroud)
你可能想做类似的事情
my $max = 5;
$s =~ s/aa/bb/ for 1..$max;
Run Code Online (Sandbox Code Playgroud)
但是对于其他模式和/或替换表达式,该方法将失败.
my $max = 5;
$s =~ s/aa/ba/ for 1..$max; # XXX Turns 'aaaaaaaa'
# into 'bbbbbaaa'
# instead of 'babababa'
Run Code Online (Sandbox Code Playgroud)
当然,每次从字符串的开头开始都可能很昂贵.