池上が言ったように、時間がかかる理由は、パターンが文字列をチャンクに分割する方法が指数関数的にあるためです。Perlの正規表現エンジンで効率的に機能させるには、バックトラックを制限する必要があります。
++
所有格の数量詞を使用してそれを行うことができます。それは、それがすべてかゼロかということによって、バックトラックを制限します。しかし、それを機能させるには、それが何に一致するかについて注意する必要があります。
[^()]++
動作しない理由(バックスラッシュは必要ありません。パレンはキャラクタークラス内で特別ではありません)は|
、より大きな正規表現が探しているキャラクターであるとも一致するためです。をバックトラックできる必要がありますが|
、他の文字をバックトラックすることはできません(正規表現の一致以外の文字で文字列を分割する(
)
か|
、正規表現の一致に役立たないため)。
これを試して:
$BRACE_MATCH = qr/ (?: [^()|]++ | \| | \((??{$BRACE_MATCH})\))* /x;
これは、それ$BRACE_MATCH
が3つのことの任意の数のシーケンスであることを示しています。
()|
(単一のチャンクとしてバックトラックされる)以外の文字列
|
キャラクター_
- バランスの取れた
(...)
表現
その理由
$BRACE_MATCH = qr/ (?: [^()]++ | \((??{$BRACE_MATCH})\))* /x;
一致しない(XX || YY) || ZZ
のは、の後に空白があること)
です。その空白は[^()]++
部分と一致しますが、文字列の残りの部分とも一致し(これ以上親がないため)、その後、その一部を返しません(所有格の数量詞であるため)。