1

この正規表現

/\(.*\)/

一致する括弧には一致しませんが、文字列の最後の括弧には一致しません。これを可能にする適切な構文を備えた正規表現拡張機能または類似のものはありますか? 例えば:

there are (many (things (on) the)) box (except (carrots (and apples)))

/OPEN(.*CLOSE)/一致する必要があります(many (things (on) the))

無限レベルの括弧が存在する可能性があります。

4

3 に答える 3

7

括弧が 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

これにより、無限のネストされたレベルと無限の並列レベルが可能になります。

ネストされたすべてのレベルを個別のキャプチャ グループとして取得することはできないことに注意してください。常に最も内側または最も外側のグループを取得します。また、このように再帰的な置換を行うことはできません。

于 2012-10-28T20:13:28.683 に答える
2

正規表現は、括弧がネストされた構造であるため、一致する括弧を見つけるのに十分なほど強力ではありません。ただし、この回答で説明されている、一致する括弧を見つけるための簡単なアルゴリズムが存在します。

式の最初の右括弧を見つけようとしているだけの場合は、正規表現で貪欲でないマッチャーを使用する必要があります。この場合、貪欲でないバージョンの正規表現は次のようになります。

/\(.*?\)/
于 2012-10-28T20:14:29.947 に答える
1

ネストされた一致する括弧を含む文字列を指定すると、最も内側のセットを次の (非再帰 JavaScript) 正規表現と一致させることができます。

var re = /\([^()]*\)/g;

または、最も外側のセットを次の (再帰的な PHP) 正規表現と一致させることができます。

$re = '/\((?:[^()]++|(?R))*\)/';

ただし、最も内側の括弧と最も外側の括弧のセットを簡単に一致させることはできません。

また、(単純で頻繁に遭遇する) 式:/\(.*?\)/は常に正しく一致しないことに注意してください (最も内側の一致セットでも最も外側の一致セットでもない)。

于 2012-10-28T20:47:47.527 に答える