Javascriptでは、文字列がabcdef
あり、この奇妙な動作を理解できません:
(?=abc)def
文字列と一致しませんabc(?=def)
文字列に一致します
なんで?
Javascriptでは、文字列がabcdef
あり、この奇妙な動作を理解できません:
(?=abc)def
文字列と一致しませんabc(?=def)
文字列に一致しますなんで?
キャプチャでは幅がゼロであり(?=abc)def
、(?=abc)
一致が成功した後、入力文字列内でカーソルを前方に移動しません。この構文は単に、次の 3 文字を先読みして、それらがabc
であるかどうかを確認し、それらが である場合は、同じ文字が であるかどうかを確認する と言っているだけdef
です。この時点で、マッチは失敗します。
一致を完了するには、正規表現エンジンがどのように機能するかを理解する必要があります。abcdef
入力文字列と正規表現を考慮してくださいabc(?=def)
。エンジンは最初に を照合し、a
次に入力文字列内のカーソルを次の文字に移動して を照合しようとします。b
入力文字列内のカーソルが一致にあるためb
です。次に、エンジンはカーソルを入力文字列内に移動し、一致を試みc
ます。カーソルは入力文字列内にあるためc
、一致は成功し、入力文字列内のカーソルは再び次の文字に移動します。エンジンはこの時点で に遭遇(?=def)
し、入力文字列内のカーソル位置から次の 3 文字が実際に存在するかどうかを確認するために先を見越します。def
カーソルを移動せずに、一致が正常に完了します。
次に、入力文字列xyz
と正規表現を考えてみましょうx(?=y)Z
。正規表現エンジンは、入力文字列の最初の文字にカーソルを置き、それが an であることを確認し、それx
を見つけたx
ので、カーソルを入力文字列の次の文字に移動します。次に、次の文字が であるかどうかを確認しますy
が、エンジンは入力テキスト カーソルの前の単語を移動しないため、入力テキストのカーソルは に留まりますy
。次に、エンジンはカーソルが文字上にあるかどうかを確認しますがz
、入力テキストのカーソルがまだ文字上にあるためy
、一致は失敗します。
http://www.regular-expressions.info/lookaround.htmlで、正と負の両方の先読みについて詳しく読むことができます 。
(?=...)
つまり、右側の文字列をテストします。先読みは、文字を食べないゼロ幅のアサーションであることにも注意してください。あなたの最初の例では:(?=abc)
つまり、その後に遭遇が続く必要がありますabc
def
。これがパターンが失敗する理由です。
def
2番目の例では、 afterが見つかりabc
、文字列が一致します
私のコメントに対するあなたの反応に基づいて、あなたが望むのは前向きな後読みだと思います:
(?<=abc)def
編集:
JavaScript を使用しているので (申し訳ありませんが、私はあなたの質問を読んだだけで、タグを見ていませんでした)、通常のキャプチャ グループを使用して、置換パターンに一致を含めてみませんか?
"abcdef".replace(/(abc)def/, "$1")
javascriptでの先読みの MDN 定義
x(?=y)
「x」の後に「y」が続く場合にのみ、「x」と一致します。これを先読みと呼びます。たとえば、
/Jack(?=Sprat)/
「Sprat」が後に続く場合にのみ「Jack」と一致します。/Jack(?=Sprat|Frost)/
'Sprat' または 'Frost' が続く場合にのみ 'Jack' に一致します。ただし、「Sprat」も「Frost」も試合結果には含まれません。
So(?=y)
の前に別のステートメント (この場合は空の文字列) がある場合、最初のステートメントの後に 2 番目のステートメントが続く場合にのみ一致します。先頭のステートメントがない場合、式(?="abc")
は最初の 3 文字 abc をキャプチャせずに一致し、それらの文字が def であるかどうかを再度確認しますが、これは失敗します。