2016-08-24 11 views
4

次の文字列と仮定します。ポイントは、私が必要だということです正規表現オプションの繰り返しのグループ

/(?: 
    \[ 
    (?: 
     \|? 
     ([^\|\[\]]+) 
    )? 
    (?: 
     \|? 
     ([^\|\[\]]+) 
    )? 
    (?: 
     \|? 
     ([^\|\[\]]+) 
    )? 
    \] 
)/ugx 

:私はこれだけ醜い正規表現(Regex101.com demo)でマッチを取得するために管理してきました

some text here [baz|foo] and here [foo|bar|baz] and even here [option].

をマッチは角括弧でグループ化されます。

[ 
    { 
    "match": 1, 
    "children": [ 
     { 
     "group": 1, 
     "start": 16, 
     "end": 19, 
     "value": "baz" 
     }, 
     { 
     "group": 2, 
     "start": 20, 
     "end": 23, 
     "value": "foo" 
     } 
    ] 
    }, 
    { 
    "match": 2, 
    "children": [ 
     { 
     "group": 1, 
     "start": 35, 
     "end": 38, 
     "value": "foo" 
     }, 
     { 
     "group": 2, 
     "start": 39, 
     "end": 42, 
     "value": "bar" 
     }, 
     { 
     "group": 3, 
     "start": 43, 
     "end": 46, 
     "value": "baz" 
     } 
    ] 
    }, 
    { 
    "match": 3, 
    "children": [ 
     { 
     "group": 1, 
     "start": 63, 
     "end": 69, 
     "value": "option" 
     } 
    ] 
    } 
] 

結果が正しいですが、その正規表現は、パターン内のブロックの繰り返しの数に制限されています だから現在私は、私は必要な結果を持っています。 sqare brackets内のすべてのオプションに一致する回避策がありますか?

+2

あなたは '[]' preg_replace_callback' 'との間のすべての値は、その後'爆発引っ張る可能性| '。 – chris85

+0

PCREスタイルエンジンを使用すると、キャプチャグループの固定マッチだけが得られます。大きなグループ内のキャプチャグループを数量化すると、再び一致する可能性がある場合、キャプチャグループは上書きされます。これはDot-Netの問題ではありません。ですから、chris85が言及するようにするか、 '\ G'構文を使用して括弧の中の個々の値(1つの一致につき1つ)を選ぶことができます。 – sln

+0

@ chris85確かに、そうすることができます。しかし、私は正規表現の出力からすべての値を取得したいと思います。 –

答えて

3

エンジンでこのような機能が提供されないため、キャプチャグループをパターン内で再帰的に生成することはできません。あなたの入力文字列中にパイプ |の出現回数に基づいて正規表現を構築する

  1. :あなたは2つのオプションがあり、と言って。

あなたが望むように、グループの試合を行います([^][|]+)の最も可能性の高い反復パターンを持つ単一の正規表現を構築することができますこの方法は:

$pattern = (function() use ($string) { 
    $array = []; 
    for ($i = 0; $i <= substr_count($string, "|"); $i++) { 
     $array[] = $i == 0 ? '([^][|]+)' : '([^][|]+)?'; 
    } 
    return implode("\|?", $array); 
})(); 

のように入力文字列を与えることによって:

some text here [baz] and here [you|him|her|foo|bar|baz|foo|option|test] and even here [another]. 

料理付き正規表現は次のようになります。

~\[([^][|]+)\|?([^][|]+)?\|?([^][|]+)?\|?([^][|]+)?\|?([^][|]+)?\|?([^][|]+)?\|?([^][|]+)?\|?([^][|]+)?\|?([^][|]+)?]~ 

Live demo

そして、あなたは単にそれを使用することができます。

preg_match_all("~\[$pattern]~", $string, $matches, PREG_SET_ORDER); 

Live demoあなたが時間を節約し、あなただけの正規表現を構築する上で頭痛を避けることができることを示すための回避策です

と正規表現されているが簡単で簡単な解決策ではありません。

  1. 他の言語機能を利用することもできます。

上記の回避策では解決策はありません。それは必要ではない多くの仕事をしています。コードの下には仕事をし合う行います

// Capture strings between brackets 
preg_match_all('~\[([^]]+)]~', $string, $matches); 

$groups = []; 

foreach ($matches[1] as $values) { 
    // Explode them on pipe 
    $groups[] = explode('|', $values); 
} 

出力は次のようになります。

Array 
(
    [0] => Array 
     (
      [0] => baz 
     ) 

    [1] => Array 
     (
      [0] => you 
      [1] => him 
      [2] => her 
      [3] => foo 
      [4] => bar 
      [5] => baz 
      [6] => foo 
      [7] => option 
      [8] => test 
     ) 

    [2] => Array 
     (
      [0] => another 
     ) 

) 

Live demo

関連する問題