5

文字列からネストされた中括弧内のすべてのコンテンツを取得することは可能ですか? 例えば:

{速い}茶色のキツネは{怠惰な}犬を{ジャンプする}

だから私は必要です:

  • 素早い
  • オーバー
  • ジャンプする

この順序で、最も入れ子になったものから優れています。

4

4 に答える 4

10

解決

以下の正規表現を使用すると、ネストされたすべての中括弧の内容を取得できます。これは、ネストされた中括弧のバランスが取れていることを前提としていることに注意してください。そうでなければ、答えがどうあるべきかを定義するのは困難です。

(?=\{((?:[^{}]++|\{(?1)\})++)\})

結果は、グループ 1 のキャプチャになります。

デモ

ただし、順序は質問で指定されているとおりではないことに注意してください。出力される順序は、開始中括弧の出現順序によって定義されます{。これは、最も外側のペアの内容が最初に出力されることを意味します。

説明

ここではゼロ幅の正の先読み を無視して、(?=pattern)内部のパターンに注目しましょう。

\{((?:[^{}]++|\{(?1)\})++)\}

2 つのリテラル中括弧の間の部分は、次のいずれかの1 つ以上のインスタンスに((?:[^{}]++|\{(?1)\})++)一致します。

  • 空でない中括弧以外の文字列[^{}]++、または
  • で囲まれたブロックに再帰的に一致します{}。これには、他の多くの非中括弧シーケンスまたは他のブロックが含まれる場合があります。

上記のパターンだけでも、不要な を含まないテキストに一致します{}。したがって、一致が2 つの両端{}の中括弧のペアで囲まれたブロックであることを確認します: .{}\{((?:[^{}]++|\{(?1)\})++)\}

ネストされたすべての中括弧内のコンテンツが必要なため、エンジンがテキストを消費しないようにする必要があります。そこで、ゼロ幅の正の先読みを使用します。

ネスト中かっこの一致をやり直すため、あまり効率的ではありませんが、それを効率的に処理できる正規表現を使用した他の一般的な解決策があるとは思えません。

通常のコードは、1 回のパスですべてを効率的に処理できるため、将来要件を拡張する場合に推奨されます。

于 2013-04-28T12:01:41.237 に答える
4

1回のパスで正規表現を使用しない簡単なソリューション:

$str = 'The {quick} brown fox {jumps {over the} lazy} dog';

$result = parseCurlyBrace($str);

echo '<pre>' . print_r($result,true) . '</pre>';

function parseCurlyBrace($str) {

  $length = strlen($str);
  $stack  = array();
  $result = array();

  for($i=0; $i < $length; $i++) {

     if($str[$i] == '{') {
        $stack[] = $i;
     }

     if($str[$i] == '}') {
        $open = array_pop($stack);
        $result[] = substr($str,$open+1, $i-$open-1);
     }
  }

  return $result;
}
于 2013-04-30T08:21:38.593 に答える
1

次のように、ハッキーで醜い方法でそれを行うことができます。

1) 正規表現のすべての一致を検索します{([^}]*)}

2)正規表現のすべての一致を検索し{([^}]*{[^}]*}[^}]*)}ます(ご覧のとおり、これは動的に構築できます)

3)正規表現のすべての一致を検索し{([^}]*{[^}]*{[^}]*}[^}]*}[^}]*)}ます...(一致がなくなるまで動的に大きく構築し続けます)

()s の外側のペアのすぐ内側にある s によって示されるキャプチャ グループ{}を使用すると、正規表現の一致全体ではなく、最初のキャプチャ グループにあるものだけを取得できます。

于 2013-04-28T00:01:34.230 に答える