5

?:正規表現の括弧の先頭に入れると、より高速であるはずの後方参照が作成されなくなることを理解しています。私の質問は、なぜこれを行うのですか?速度の向上は、この考慮事項を正当化するのに十分なほど顕著ですか? どのような状況で、後方参照を使用しないときは毎回慎重に後方参照をスキップする必要があるほど重要になるのでしょうか。もう 1 つの欠点は、正規表現の読み取り、編集、および更新が難しくなることです (後で後方参照を使用する場合)。

要約すると、逆参照を作成しないのはなぜでしょうか?

4

2 に答える 2

13

\1のような後方参照とグループのキャプチャを混同していると思います(...)

後方参照は、言語を非正規化することにより、あらゆる種類の最適化を防ぎます。

グループをキャプチャすると、正規表現エンジンがグループの開始位置と終了位置を覚える作業が少し増えますが、後方参照ほど悪くはありません。

http://www.regular-expressions.info/brackets.htmlでは、グループのキャプチャとそれらへの後方参照について詳しく説明しています。

編集:

正規表現を非正規にする後方参照については、lua コメントに一致する次の正規表現を検討してください。

/^--(?:\[(=*)\[[\s\S]*?(?:\]\1\]|$)|[^\r\n]*)/

コメントです--[[...]]--[=[...]=]コメント--[==[...]==]です、コメントです。角かっこの間に等号を追加することで、コメントをネストできます。

これは厳密に通常の言語では対応できないため、単純な有限状態マシンでは O(n) 時間で処理できません。カウンターが必要です。

Perl 5 の正規表現は、後方参照を使用してこれを処理できます。しかし、非正規パターン マッチングが必要になるとすぐに、正規表現ライブラリは単純なステート マシン アプローチを放棄し、より複雑で非効率的なコードを使用する必要があります。

于 2011-03-14T02:01:00.943 に答える
6

おっしゃるとおり、グループのキャプチャを避ける理由はパフォーマンスだけではありません。実際、それは最も重要な理由でもありません。

もう 1 つの欠点は、正規表現の読み取り、編集、および更新が難しくなることです (後で後方参照を使用する場合)。

私はこれを逆に見ています。非キャプチャ グループを習慣的に使用している場合は、何かをキャプチャすることを選択し場合にグループ番号を追跡する方が簡単です。同じように、名前付きグループを使用している場合 (正規表現がそれらをサポートしていると仮定)、常に名前付きグループを使用し、(後方参照または置換文字列で) 番号ではなく名前で参照する必要があります。これらのルールに一貫して従うことで、非キャプチャ グループの読みやすさのペナルティを少なくとも部分的に相殺できます。

はい、それはあなたの正規表現をそのように混乱させなければならないPITAであり、正規表現の実装を書いたり維持したりする人々はそれを知っています。.NET では、ExplicitCaptureすべての「裸の」括弧を非キャプチャ グループとして扱い、名前付きグループのみをキャプチャするオプションを設定できます。Perl 6 では、括弧 (名前の有無にかかわらず) は常にキャプチャし、角括弧は非キャプチャ グループに使用されます。他のフレーバーも最終的には同じようになるでしょうが、それまでは良い習慣に頼るしかありません。

于 2011-03-14T10:20:55.380 に答える