2

次の正規表現が一部の文字列で機能し、他の一部の文字列では機能しない理由が不思議です。

/^([0-3]+)(?!4|.*5)[0-9]+$/

1151 -> これは一致しません

1141 -> これは一致しますが、なぜですか? .* を空と見なすことができるので、正規表現は次のようになります/^([0-3]+)(?!4|5)[0-9]+$/

先読みの仕組みを誤解していると思います...

4

4 に答える 4

9

正規表現が文字列をどのように解析するかを、順を追って見ていきましょう。

^([0-3]+)(?!4|.*5)[0-9]+$

まず、いくつかの説明。またはが最後に消費された文字に続く(?!4|.*5)かどうかをチェックする否定的な先読みです。そうである場合、現在の一致は失敗し、後退します。また、正確にどのように影響するかをもう少し明確にしたい場合にも使用できます。 4.*5(?!(4|.*5))|

見ることから始めましょう1141

まず、[0-3]+可能な限り多くの文字を消費するため、最大で11inを消費し1141ます。残っているのは41. 4正規表現は現在の文字の後にあるかどうかを確認する?!ようになりました。 は否定的な先読みであるため、見つかった場合、一致は失敗します。followingで4ある11ため、一致は失敗し、正規表現は後退して再試行します。

2 つのに一致する代わりに、1 つ1の一致を試行し、残ったものと一致1するようになり141ました。?!4次の文字があることを確認するためにチェックし4、何を知っていますか、そこにはありません。一致しなかったため、正規表現は否定的な先読みを残し、残りの正規表現に進みます。141は最終的に一致するため、文字列[0-9]+全体が一致します。ルックアラウンドは文字を消費しないことに注意してください。1141

それでは見てみましょう1151

前回と同じことが起こり、11消費されて51余ってしまいました。次に、否定先読みを見て、それから残りの文字列を評価します。明らかに、4はこの文字列のどこにもないので無視できます.*5

したがって、先読み.*5は と一致しようとし51ます。一致してしまうと、前と同じように一致が失敗し、正規表現が後退します。正規表現を少しでも知っていれば、空と評価される可能性があるため.*5、の先頭に一致することは明らかです。51.*

一歩下がって、今度は1両方ではなく 1 つを一致させ、再び否定的な先読みを行います。

現在、 を消費していますが1、まだ151一致する必要が(?!4|.*5)あり、正規表現の一部になっています。ここで、4は明らかに文字列に存在しないため、一致しません.*5。もう一度見てみましょう。

.*5 will match a portion of 151 since .* will consume the first 1, and the 5 will finish off by matching 5. This should also be obvious if you know regex.

So we've made a match in a negative look-ahead again, which is bad... so we step back again. We have no more integers to attempt to match with [0-3], and since you can't match 0 integers with a +, the entire string fails to match the regular expression.

于 2013-01-29T16:34:31.960 に答える
2

1141これは、正規表現エンジンが11との[0-3]+一致から最初のとの一致1に戻り、残りの数字を[0-9]+.

最初の文字の後の次の文字11and not4であるため、次の文字のみを見る否定的な先読みは一致を妨げません。

が追加された負の1151先読み.*によって防止されるため、 は一致しません。

先読みの.*前に put を追加すると、「次の文字が の場合は一致しない」 、または任意の数の文字の後に次の文字が' (改行を無視) の場合は一致しません。 545

したがって、エンジンが の最初の部分[0-3]+だけを一致させるためにバックトラックしたとしても、文字列にはまだ前方があるため、一致は妨げられます。111515

先読みと後読みはゼロ幅であることに注意してください。

于 2013-01-29T16:22:35.743 に答える
0

それはどの正規表現のフレーバーですか?

/^([0-3]+) (?!4|.*5) [0-9]+$/

正直なところ、1151 ではなく 1141 に一致する唯一の方法は、正規表現の強調表示された部分が として評価される場合NOT 4 or .* followed by 5です。その場合、正規表現エンジンは11414 に一致するため一致を見つけることができませんが、内部一致を完了するために 5 を見逃すことになります。

ただし、エンジンが一致を機能させたい場合、この表現は非常に強力であることが証明されるため、通常、代替は4or .*5- として理解されますが、これはまだ 4 または 5 と同等ではありません。.*

式を何でテストしていますか?

于 2013-01-29T16:19:43.047 に答える
0

4または5に一致させたい場合、最良のオプションは

/^[0-3]+[45][0-9]+$/

しかし、それが何をすべきかについてのより良い説明がなければ、それ以上のことを提案するのは難しいです...

于 2013-01-29T15:18:45.167 に答える