私は正規表現を持っています:
(<select([^>]*>))(.*?)(</select\s*>)
レイジーリピート量指定子を使用するため、長い文字列(500を超えるオプションがある)の場合、100,000回を超えてバックトラックし、失敗します。遅延反復数量詞を使用しない、より良い正規表現を見つけるのを手伝ってください
私は正規表現を持っています:
(<select([^>]*>))(.*?)(</select\s*>)
レイジーリピート量指定子を使用するため、長い文字列(500を超えるオプションがある)の場合、100,000回を超えてバックトラックし、失敗します。遅延反復数量詞を使用しない、より良い正規表現を見つけるのを手伝ってください
<select[^>]*>[^<]*(?:<(?!/select>)[^<]*)*</select>
...または人間が読める形式:
<select[^>]*> # start tag
[^<]* # anything except opening bracket
(?: # if you find an open bracket
<(?!/select>) # match it if it's not part of end tag
[^<]* # consume any more non-brackets
)* # repeat as needed
</select> # end tag
これは、Friedlが彼の著書「 MasteringRegularExpressions」で開発した「展開ループ」手法の例です。気が進まない数量詞に基づくパターンを使用して、RegexBuddyで簡単なテストを行いました。
(?s)<select[^>]*>.*?</select>
...そして一致するものを見つけるのに約6,000ステップかかりました。展開されたループパターンは500ステップしかかかりませんでした。また、終了タグ()から閉じ括弧を削除し</select
て一致を不可能にした場合、失敗を報告するのに必要な手順は800ステップのみでした。
正規表現フレーバーが所有格の数量詞をサポートしている場合は、それらも使用してください。
<select[^>]*+>[^<]*+(?:<(?!/select>)[^<]*+)*+</select>
一致を達成するためにほぼ同じ数のステップが必要ですが、プロセスで使用するメモリが大幅に少なくなります。そして、一致する可能性がない場合、それはさらに迅速に失敗します。私のテストでは、一致するものを見つけるのにかかったのと同じ数の約500ステップを要しました。
残念ながら、これは機能しません。正しい例については、AlanMooreの回答を参照してください。
(<select([^>]*>))(.*+)(</select\s*>)
perl regexpのマンページから:
デフォルトでは、定量化されたサブパターンがパターン全体の残りの部分を一致させることができない場合、Perlはバックトラックします。ただし、この動作は望ましくない場合があります。したがって、Perlは「所有格」の数量詞形式も提供します。
*+ Match 0 or more times and give nothing back
++ Match 1 or more times and give nothing back
?+ Match 0 or 1 time and give nothing back
{n}+ Match exactly n times and give nothing back (redundant)
{n,}+ Match at least n times and give nothing back
{n,m}+ Match at least n but not more than m times and give nothing back
例えば、
'aaaa' =~ /a++a/
「a++」は文字列内のすべての「a」を飲み込み、パターンの残りの部分には何も残さないため、一致することはありません。この機能は、バックトラックしてはいけない場所についてのPerlのヒントを与えるのに非常に役立ちます。たとえば、一般的な「二重引用符で囲まれた文字列に一致する」問題は、次のように記述すると最も効率的に実行できます。
/"(?:[^"\\]++|\\.)*+"/