括弧が 1 レベルしかない場合は、2 つの可能性があります。
オプション 1:貪欲でない繰り返しを使用する:
/\(.*?\)/
これは、最初の に遭遇すると停止し)
ます。
オプション 2:負の文字クラスを使用する
/\([^)]*\)/
これは、ではない文字のみを繰り返すこと)
ができるため、必ずしも最初の閉じ括弧を超えることはできません。通常、パフォーマンス上の理由から、このオプションが推奨されます。さらに、このオプションはより簡単に拡張され、括弧をエスケープできるようになります (これにより、 を破棄する(some\)thing)
代わりに、この完全な文字列に一致させることができますthing)
)。しかし、これが必要になることはおそらくめったにありません。
ただし、ネストされた構造が必要な場合、これは通常、正規表現には複雑すぎます (ただし、PCRE などの一部のフレーバーは再帰パターンをサポートします)。この場合、現在のネストレベルを追跡するために、自分で文字列を調べて括弧を数えるだけです。
これらの再帰的なパターンについての補足として: PCRE では(?R)
単純にパターン全体を表すので、これをどこかに挿入すると全体が再帰的になります。ただし、括弧のすべての内容は、一致全体と同じ構造でなければなりません。また、複数のネストされたレベルでキャプチャ グループを使用するだけでなく、これで意味のある 1 ステップの置換を行うことは実際には不可能です。全体として、ネストされた構造に正規表現を使用しないのが最善です。
更新:正規表現ソリューションを見つけたいと思っているようですので、PCRE (PHP での実装例) を使用して例を一致させる方法を次に示します。
$str = 'there are (many (things (on) the)) box (except (carrots (and apples)))';
preg_match_all('/\([^()]*(?:(?R)[^()]*)*\)/', $str, $matches);
print_r($matches);
結果は
Array
(
[0] => Array
(
[0] => (many (things (on) the))
[1] => (except (carrots (and apples)))
)
)
パターンの機能:
\( # opening bracket
[^()]* # arbitrarily many non-bracket characters
(?: # start a non-capturing group for later repetition
(?R) # recursion! (match any nested brackets)
[^()]* # arbitrarily many non-bracket characters
)* # close the group and repeat it arbitrarily many times
\) # closing bracket
これにより、無限のネストされたレベルと無限の並列レベルが可能になります。
ネストされたすべてのレベルを個別のキャプチャ グループとして取得することはできないことに注意してください。常に最も内側または最も外側のグループを取得します。また、このように再帰的な置換を行うことはできません。