正規表現が遅い理由は、それらがひどく書かれているからです。
では、なぜ彼らが悪いのかを述べていきましょう。
最初の式には不要なトークンがたくさんあります。先頭と末尾など、.*
違いはありません。次に、<
0 から inf までの時間を定量化しました。なんで?あなたは一致したい<<<<<<<<email>
ですか?またはemail>
?最後に、繰り返しグループを数量化しました。これは恐ろしいから
- 定量化されたキャプチャ グループはそれ自体を上書きします
- 上記のステートメントにより、キャプチャ グループを使用しても意味がなく、不要なリソースが使用されます。
さて、それが最初の表現です。に切り替えたばかりなのに、2番目のものはさらに悪い<>
です[]
。なぜあなたは尋ねるかもしれませんか?その理由をお話しします。一致しないため。なぜこれがそんなに悪いのですか?それは私たちが壊滅的なバックトラッキングと呼ぶものを生み出すからです。なぜこれを行うのでしょうか? その理由を説明します。
.*
可能な限り一致するようにします。実際、最初は文字列全体を消費します。明らかにそれは失敗するため、最初の に一致するまで何度もバックトラックします[
。これで、エンジンはリテラルの文字列の最初の位置で一致を見つけました[
(したがって、.*
一致は何もありません)。次のトークンは、.*
貪欲な性質により、再びすべてに一致します。これは機能しないため、エンジンはバックトラックします。文字列に一致するまで、これを試行し続けます。問題は、決してそうならないことです。貪欲な量指定子が、1 つ以上の一致を必要とする量化されたグループに囲まれているためです。
さて、これをどのように修正しますか?+
グループの後ろから を簡単に削除できます。それはそれを修正します。正規表現は依然としてひどいものですが、エンジンが何百万回もバックトラックすることはありません。どうすればそれをさらに改善できますか?否定文字クラスを使用する。
/\[([^]]+)\] <([^>]+)>/
ここで正規表現のデモを表示: http://regex101.com/r/wS2jN0
最初に regex101.com を使用していた場合、バックトラッキングの問題にすぐに気付くでしょう: http://regex101.com/r/vB8xB0