私の毎日の仕事はPerlで90%であるため、私は日常的に正規表現を使用しています(レガシーコードベースですが、それは別の問題です)。それにもかかわらず、私はまだ先読みと後読みがひどく混乱していて、しばしば読めないことに気づきます。今のところ、先読みまたは後読みでコードレビューを取得する場合は、すぐにそれを送り返して、複数の正規表現または別のアプローチを使用して問題を解決できるかどうかを確認します。以下は、私がそれらを好きにしない傾向がある主な理由です。
さて、特に最後の二つの理由は本当にいいものではないことは認めますが、一つ見たときに頭のなかで何が起きているのかを列挙しておかなければならないと感じました。私はそれらについての考えを変えたいと思っていますが、それらは次のようなプログラミングの私のコア原則のいくつかに違反していると感じています。
私の質問はこれです:正規表現で先読み/後読みを使用するのは良い習慣ですか、それとも現代のプロダクションコードに侵入した単なるハックですか?
私はこれについて間違っていると確信できて完全にうれしいです。簡単な例は例や説明に役立ちますが、それだけでは私を納得させるのに十分ではありません。
私はまだ先読みと後読みがひどく混乱していて、しばしば判読できないことに気づきます。
正規表現を分解してコメントできることをご存知ですか?
$foo =~ m/^
(?=.*a) # must contain an a somewhere
(?=.*c) # must contain a c somewhere
(?=.*1) # must contain a 1 somewhere
(?=.*2) # must contain a 2 somewhere
\S+ # all non-space characters
$/x
正規表現で先読み/後読みを使用することは良い習慣ですか、それとも単に最新の製品コードへの道を見つけたハックですか?
壊滅的なバックトラッキング および 正規表現関連のセキュリティ問題 を回避するために、これらは非常に不可欠です。理想的にはプレーン アトミックグループ も使用します。
ナイーブな同等物と比較して、上記の式がどのようにバックトラックするかを比較します。
$foo =~ m/^
\S*a\S*c\S*1\S*2\S* # a, then c, then 1, then 2
|
\S*a\S*c\S*2\S*1\S* # a, c, 2, 1
|
\S*a\S*1\S*c\S*2\S* # a, 1, c, 2
|
\S*a\S*1\S*2\S*c\S* # a, 1, 2, c
|
# ... etc
$/x
特に、長い入力とa、c、2(1なし)のランダムシーケンスを使用します。
非常に一般的な見方をするためには、お互いのトレードオフを比較検討する必要があります。一方では、いくつかの実装でのみサポートされている高度な機能があります。これは、非常に熟練していないと読みにくいものです。もう1つは、より単純な構成を使用した(非常に長いと思われる)コードの断片です。どちらが最適かは、アクセシビリティ(元のプログラマーとあなた自身のの習熟度)およびaccuracyやspeedなどのより抽象的な懸念事項-)。原則として、私自身の意見(約10年間正規表現を使用した後):
substr
/if-else
構築は非常に高速である可能性があるため、アプローチを実行する前に試してください。