5

同じ奇妙な結果(javaScriptとFlash)を生成する次の正規表現を2つの言語で使用しています。私が知りたいのは、それを修正する方法ではなく、なぜその動作が起こっているのかです。正規表現でキャプチャグループの最後のインスタンスのみをキャプチャします

正規表現:

\[(\\{2}|\\\]|[^\]])*\] 

ここでの目標は、角括弧で囲まれた文字列に一致する、と私はエスケープブラケットで停止しないようにすることです。

テキスト入力が[abcdefg]の場合は正しくマッチングされますが、キャプチャグループの一部として返されるのはgです(ここではabcdefgとなります)。式を \[((?:\\{2}|\\\]|[^\]])*)\]に変更すると、結果が得られます。

なぜこのようなことが起こっていますか?これは他の言語でも一貫しますか?

注:式を\[([^\]])*\]に簡略化すると同じ問題が発生します。このようなキャプチャグループ内の*数量詞を含む

答えて

7

彼らは両方のECMAScript(またはそのスーパーセットを実装するようにかかわらず、問題の、ActionScriptとJavaScriptは常に、同じ結果が得られるはずです、正規表現の場合は同意しないでください)。

はい、これはどの言語(または正規表現のフレーバー)でも起こります。その理由は、キャプチャグループを繰り返しているためです。もっと簡単な例を考えてみましょう:(.)*abcとの一致。だから私たちが繰り返すのは(.)です。初めて試行されると、エンジンがグループに入り、aと一致して.となり、グループを離れてaをキャプチャします。数量化が始まり、それがすべて繰り返されます。グループに再び入って、bとマッチしてキャプチャします。このキャプチャは前のキャプチャを上書きします。したがって、\1にはbが含まれます。 3回目の繰り返しでも同じです。キャプチャはcで上書きされます。

異なる動作をする正規表現のフレーバはわかりません。上書きするのではなく、以前のすべてのキャプチャにアクセスできる唯一のものは.NETです。

解決策は、1p.sg。提案された。繰り返しのために必要なグループ化を非キャプチャにします(これはキャプチャと上書きをすべて必要としないためパフォーマンスが向上します)、新しいグループにすべてをラップします。あなたの表現には小さな欠点が1つあります。ネゲートされた文字クラスにバックスラッシュを含める必要があります。そうしないと、バックトラッキングは[abc\]に一致する可能性があります。だからここにあなたが期待通りに動作します式です:

\[((?:\\{2}|\\\]|[^\]\\])*)\] 

Working demo.(残念ながら、それはキャプチャを示していないが、それはそれはすべてのケースで正しい対応を与えることを示している)

注あなたのことをexpressionは他のエスケープシーケンスを許さない。特に\という単一の文字と、それに続く]という文字のいずれかが続くと、パターンが失敗します。これはあなたが望むものではない場合、あなただけ使用することができます。

\[([^\]\\]*(?:\\.[^\]\\]*)*)\] 

Working demo.

\[((?:\\.|[^\]\\])*)\] 

Working demo.

パフォーマンスがさらに"unrolling-the-loop"技術を向上させることが可能

2

してみてください:

\[((?:\\{2}|\\\]|[^\]])*)\] 
関連する問題