各行で非常に多くの一致があった後にのみ開始する単純な文字列を検索して置換したい、たとえば:
n=2 の場合は s/ZZ/YY
xxxZZxxxxxxZZxxxxZZxZZxxxxZZ
xZZxxxZZxxZZxxZZxZZxxxZZxxx
...
の中へ:
xxxZZxxxxxxZZxxxxxYYxxxxYY
xZZxxxZZxxYYxxYYxYYxxxYYxxx
...
私の問題では、連続する「ZZ」の間に常に「x」があります。前もって感謝します。
これまでに見られた一致の数を数えることができる実行可能な置換文字列をお勧めします
このコードは
use strict;
use warnings;
while (<DATA>) {
my $n = 0;
s/(ZZ)/$n++ < 2 ? $1 : 'YY'/eg;
print;
}
__DATA__
xxxZZxxxxxxZZxxxxZZxZZxxxxZZ
xZZxxxZZxxZZxxZZxZZxxxZZxxx
出力
xxxZZxxxxxxZZxxxxYYxYYxxxxYY
xZZxxxZZxxYYxxYYxYYxxxYYxxx
おそらく、後読みの解決策、または文字列を逆にして先読みし、もう一度逆にする解決策があります(もしあれば、私はそれらに賛成します)が、私は通常while
、発見しやすく、間違いなく読みやすくなります。
1 while $string =~ s/(ZZ.*ZZ.*)ZZ/$1YY/
つまり、文字列には3つのパターンが含まれていますがZZ
、3番目のパターンを。に置き換えYY
ます。
一般的な解決策として:
$expr = (quotemeta($pattern1) . ".*") x $n;
1 while $string =~ s/($expr)\Q$pattern2\E/$1$pattern2/;
1 while $thisline=~s/((?:x*?ZZx*?){2}[xZY]*?)ZZ/$1YY/;
これは n=2 の場合の解です。
n の他の値については、そこで数値を変更するだけです。
また、遅延マッチングを使用して置換を最適化し、余分なキャプチャーを排除しました。
最も単純な 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