0

列ではない、またはエスケープされた列である一連の文字を認識する単純な正規表現を作成しようとしています。すなわち:

foo:bar //Does not match

しかし

foo\:bar //Does match

正規言語に関する私の知識では、そのような言語は正規表現で記述できます

/([^:]|\\[:])*/

すばらしいツールRegexperで、この式のグラフィカルな表現を見ることができます。

php の( PCREpreg_matchエンジンに基づく) を使用すると、このような式は "foo\:bar" と一致しません。

ただし、クラスを単一の文字に置き換えると、次のようになります。

/([^:]|\\:)*/

表現が一致します。

これについて説明はありますか?これは、文字クラスに対する PCRE エンジンの一種の制限ですか?

PS: AS3 Regexp エンジンに基づくRegExrで最初の式をテストすると、代替順序を変更しながら一致が得られません。

/(\\[:]|[^:])*/

一致しますが、同じ式は PCRE では一致しません。

4

2 に答える 2

1

preg_match()正規表現パターンを文字列として受け入れるため、すべてを二重にエスケープする必要があります。

^(?:[^:\\\\]|\\\\:)+$

これは、コロンでもエスケープ文字でもない 1 つ以上の文字[^:\\\\]、またはエスケープされたコロンに一致し\\\\:ます。

最初の正規表現が機能しなかった理由: /([^:]|\\[:])*/.

これは、コロン以外の[^:]と一致するか\\[:]、リテラルの後にリテラルとリテラル[が続くものと一致します。:]

これが機能する理由: /([^:]|\\:)*/?

これは非コロン[^:]に一致するか、リテラルに一致する\\:ため、事実上すべてに一致します。

編集:なぜ/([^:]|E[:])*/一致しないのfooE:barですか?

これが起こることです:に[^:]一致し、f次に一致し、次にo他のものに一致し、o次に に一致しEます。コロンが見つかり、:一致することはありませんが、デフォルトでは、PCRE エンジンは可能な限り最長の一致を探しません。これまでに一致したもので、その場で停止fooEし、他の選択肢E[:] (ちなみに と等しいE:)をまったく試行せずに一致として返されます。

シーケンス全体を一致させたい場合は、次のような式を使用します。

/([^:E]|E[:])*/

これにより[^:]、それを消費できなくなりEます。

于 2013-10-17T11:14:05.000 に答える
1

これを試すことができます。これにより、セキュエンス\\:は、否定された文字クラスの前にチャンスを持つことができ[^:]ます。

^(?:\\:|[^:])+$

代替バーの値を反転して使用すると、^((?:[^:]|\\:)+$エスケープされたコロンと一致しません。これは、最初の代替が2 番目の式が試行される前に\:スラッシュ ( ) を消費するためです。\

于 2013-10-17T11:10:40.863 に答える