編集 2:これが依然として重要である理由の実用的なデモンストレーションについては、 stackoverflow 自身の正規表現による停止 (2016-07-20) を参照してください。
編集:この質問は、私が最初に尋ねたときからかなり進化しました。2 つの高速で互換性があるが、完全な機能を備えていない実装については、以下を参照してください。より多くの、またはより優れた実装を知っている場合は、それらについて言及してください。ここにはまだ理想的な実装はありません!
確実に高速な正規表現の実装はどこにありますか?
.NETまたはネイティブで.NETから合理的に使用できる、通常の非バックトラッキング(バックトラック)線形時間正規表現の実装を知っている人はいますか? System.Text.RegularExpressions
有用であるためには、次のことが必要です。
- 正規表現の長さを m、入力の長さを n とすると、最悪の場合の正規表現評価の時間複雑度はO(m*n)になります。
- O(n) の通常の時間の複雑さを持ちます。これは、正規表現が実際に指数状態空間をトリガーすることはほとんどないか、可能であれば、入力のわずかなサブセットでのみトリガーするためです。
- 合理的な構築速度がある(つまり、潜在的に指数関数的な DFA がない)
- 数学者ではなく、人間が使用することを意図したものにする - たとえば、Unicode 文字クラスを再実装したくない: .NET または PCRE スタイルの文字クラスはプラスです。
ボーナスポイント:
- O(m)メモリではなくO(n + m)メモリを消費してネストを処理できるスタックベースの機能を実装する場合、実用性のボーナスポイント。
- 部分式または置換をキャプチャするためのボーナス ポイント(部分式の一致の可能性が指数関数的に存在する場合、それらすべてを列挙することは本質的に指数関数的ですが、最初のいくつかを列挙することはすべきではなく、置換についても同様です)。他の機能を使用することで、どちらかの機能が欠けていることを回避できるため、どちらかがあれば十分です。
- 正規表現をファーストクラスの値として扱うための多くのボーナスポイント(したがって、結合、交差、連結、否定を取ることができます-特に否定と交差は、正規表現定義の文字列操作によって行うのが非常に難しいため)
- 遅延マッチング、つまり、すべてをメモリに入れずに無制限のストリームでマッチングすることはプラスです。ストリームがシークをサポートしていない場合、部分式や置換をキャプチャすることは (一般に) 1 回のパスでは不可能です。
- 後方参照は outです。基本的に信頼できません。つまり、異常な入力ケースが与えられると、常に指数関数的な動作を示すことができます。
そのようなアルゴリズムは存在します (これは基本的なオートマトン理論です...) - しかし、.NET からアクセスできる実際に使用可能な実装はありますか?
背景: (これはスキップできます)
私は迅速で汚れたテキストのクリーンアップに Regex を使用するのが好きですが、perl/java/python/.NET で使用される一般的なバックトラッキング NFA 実装が指数関数的な動作を示すという問題に繰り返し遭遇しました。残念ながら、これらのケースは、正規表現の自動生成を開始するとすぐに、かなり簡単にトリガーされます。同じプレフィックスに一致する正規表現を交互に使用すると、指数関数的でないパフォーマンスでさえ非常に悪くなる可能性があります。たとえば、非常に基本的な例で、辞書を取得して正規表現に変換すると、ひどいパフォーマンスが予想されます。
より優れた実装が存在し、60 年代以降存在している理由の簡単な概要については、「正規表現の照合はシンプルかつ高速にできる」を参照してください。
あまり実用的ではないオプション:
- ほぼ理想的: FSA ツールキット。正規表現を DFA + NFA の高速な C 実装にコンパイルでき、変換器 (!) も許可され、交差とパラメーター化の構文を含むファーストクラスの正規表現 (カプセル化 yay!) があります。 しかし、それはプロローグです...(この種の実用的な機能を備えたものが主流の言語で利用できないのはなぜですか???)
- 高速ですが実用的ではありません: 優れたANTLRなどの完全なパーサーは、一般的に確実に高速な正規表現をサポートします。ただし、antlr の構文ははるかに冗長であり、もちろん、有効なパーサーを生成しない可能性のある構成を許可するため、安全なサブセットを見つける必要があります。
良い実装:
- RE2 - 適切な PCRE 互換性から後方参照を除外することを目的とした Google オープン ソース ライブラリ。作者によると、これは plan9 の正規表現 lib の unix ポートの後継だと思います。
- TRE - PCRE とほとんど互換性があり、逆参照も行いますが、それらを使用すると速度の保証が失われます。しかも超おまけマッチングモード搭載!
残念ながら、どちらの実装も C++ であり、.NET から使用するには相互運用が必要です。