Perlで、文字列ごとに最大N個の一致のみを置き換える正規表現を作成するにはどうすればよいですか?
s/aa/bb/;
つまり、との中間点を探していs/aa/bb/g;
ます。複数の置換を許可したいのですが、N回までです。
私は3つの信頼できる方法を考えることができます。1つ目は、N回目の試合後のすべてを自分自身に置き換えることです。
my $max = 5;
$s =~ s/(aa)/ $max-- > 0 ? 'bb' : $1 /eg;
N以上の一致がある場合、これはあまり効率的ではありません。そのためには、ループを正規表現エンジンの外に移動する必要があります。次の2つの方法はそれを行う方法です。
my $max = 5;
my $out = '';
$out .= $1 . 'bb' while $max-- && $in =~ /\G(.*?)aa/gcs;
$out .= $1 if $in =~ /\G(.*)/gcs;
そして今回は、インプレース:
my $max = 5;
my $replace = 'bb';
while ($max-- && $s =~ s/\G.*?\Kaa/$replace/s) {
pos($s) = $-[0] + length($replace);
}
あなたは次のようなことをしたくなるかもしれません
my $max = 5;
$s =~ s/aa/bb/ for 1..$max;
ただし、そのアプローチは、他のパターンや置換式では失敗します。
my $max = 5;
$s =~ s/aa/ba/ for 1..$max; # XXX Turns 'aaaaaaaa'
# into 'bbbbbaaa'
# instead of 'babababa'
そしてもちろん、毎回文字列の最初から始めるのは費用がかかる可能性があります。
正規表現では必要なことはできません。ただし、置換をforループに入れることができます。
my $i;
my $aa = 'aaaaaaaaaaaaaaaaaaaa';
for ($i=0;$i<4;$i++) {
$aa =~ s/aa/bb/;
}
print "$aa\n";
結果:
bbbbbbbbaaaaaaaaaaaa
/e
右側を評価するフラグを式として使用できます。
my $n = 3;
$string =~ s/(aa)/$n-- > 0 ? "bb" : $1/ge;
/ e修飾子を使用した解決策は次のとおりです。これを使用して、perlコードを使用して置換文字列を生成できます。
私の$count= 0; $ string =〜s {$ pattern} {{ $ count ++; if($ count <$ limit){ $ replace; } そうしないと { $&; #ノーオペレーションを偽造し、元の一致に置き換えます。 } } xeg;
perl 5.10以降では、$&(パフォーマンスが奇妙に複雑になる)を削除し、/p修飾子を介して${^MATCH}を使用できます。
$ string =〜s {$ pattern} {{ $ count ++; if($ count <$ limit){ $ replace; } そうしないと { $ {^ MATCH}; } } xegp;
これを行うことができないのは残念ですが、次のことはできません。
$ count> =$limitの場合は最後。