$s = "bla..bla";
$s =~ s/([^%])\./$1/g;
.
後ではないすべての出現を%
前の文字に置き換える必要があると思います.
。
しかし$s
、それは:bla.bla
ですが、そうあるべきですblabla
。問題はどこだ?数量詞を使用できることはわかっていますが、この方法で使用する必要があります。
グローバル正規表現が文字列を検索しているとき、重複する一致は見つかりません。
文字列の最初の一致は、になりa.
、これは。に置き換えられa
ます。正規表現エンジンが検索を再開すると、次の文字列から開始される.
ため、文字列の残りの部分と見なさ.bla
れます。正規表現では、文字が一致する必要がある.
ため、再度一致することはできません。
代わりに、ネガティブルックビハインドを使用して、前の文字がそうではないというアサーションを実行します%
。
$s =~ s/(?<!%)\.//g;
のようなポジティブルックビハインドを使用する場合、それが文字列の最初の文字である場合(?<=[^%])
は置き換えられないことに注意してください。.
問題は、/g
フラグがあっても、各置換が前の置換が中断したところから探し始めることです。で置き換えようとしa.
てa
いa.
ますが、前の置き換えですでに「飲み込まれている」a
ため、2番目の置き換えは発生しません。a
1つの修正は、ゼロ幅のルックビハインドアサーションを使用することです。
$s =~ s/(?<=[^%])\.//g;
これにより、文字列の最初の文字では.
なく、前に。が付いていない文字がすべて削除され%
ます。
しかし、実際にはこれが必要な場合があります。
$s =~ s/(?<!%)\.//g;
これにより、文字列の最初の文字であっても、先頭にない.
ものはすべて削除されます。%
後読みよりもはるかに簡単な方法は、次の方法を使用することです。
$s =~ s/([^%])\.+/$1/g;
これは、何もない以外の文字の後の1つ以上のドットの文字列を置き換えます%
。