正規表現の仕組みを誤解しているようです。私はあなたのためにそれを打破してみましょう:
(?= lookahead assertion: the following pattern must match, but
will not consume any of the text.
(.{3})* matches a series of 3 characters, any number of times. In
other words, this consumes characters in multiples of 3.
(.{4})$ makes sure there are exactly 4 characters left.
)
このパターンは、あなたがダッシュ-
を挿入したいすべての場所に空試合を生成します。そのため、preg_replace("/(?=(.{3})*(.{4})$)/", "-", "1231231234");
は正しい場所にのダッシュを挿入します。空の文字列を置き換えることは挿入と同じです。のは、一例として、テキスト31231234
を使用して、そのステップ・バイ・ステップを見てみましょう:パターンは、テキスト内の位置0に一致させることができなかった
remaining text remaining pattern what happens
step 0: 31231234 (.{3})*(.{4})$ (.{3})* matches one time
step 1: 31234 (.{3})*(.{4})$ (.{3})* matches again
step 2: 34 (.{3})*(.{4})$ (.{3})* fails to match another time
step 3: 34 (.{4})$ (.{4}) fails to match -> backtrack
step 5: 31234 (.{4})$ (.{4}) fails to match -> pattern failed to
match, no dash will be inserted.
した後、それは位置1で再度チェックされます(残りのテキストがあります1231234
):
remaining text remaining pattern what happens
step 0: 1231234 (.{3})*(.{4})$ (.{3})* matches one time
step 1: 1234 (.{3})*(.{4})$ (.{3})* matches again
step 2: 4 (.{3})*(.{4})$ (.{3})* fails to match another time
step 3: 4 (.{4})$ (.{4})$ matches -> dash will be inserted
here, giving "3-1231234"
同じことは、最終結果3-123-1234
を与え、3つの文字後に再び起こります。つまり、グループ(.{4})$
は、テキストの最後の4文字にダッシュを挿入しないことを指定します。最後の4文字を消費することで、残っている文字数が4文字未満の場合、パターンが一致しなくなります。そのため、(.{4})(.{4})$
と(.{4}){2}$
の両方が8文字のブロックを生成します。パターンは8文字未満であれば一致できません。
は、最後の8つの文字で、別のダッシュを挿入するために、あなたは4つの文字.{4}
の2つのグループを使用して、それらのいずれかをオプションにする必要があります:
(?=((.{3})*.{4})?(.{4})$)
詳細な説明をありがとうございます。もう1つの質問。 $を使用すると、実際にその時点からのバックトラック検索ですか、または何らかの種類の左から右への繰り返しですか?たとえば、この簡単なテストでは、https://regex101.com/r/eE6zK7/1には、一致が20ステップ後に見つかったと表示されています。 – Rafael
@Rafael: '$'は文字列の終わりのアンカーに過ぎず、正規表現の "方向"には影響しません。 regex101上で "debugger"をクリックすると、それがどのように一歩一歩見えるかがわかります。 –