2013-02-14 2 views
2

В PHP У меня есть строка с вложенными скобками:PHP: preg_match_all, который сначала соответствует внутренним скобкам?

bar[foo[test[abc][def]]bar]foo 

мне нужен регулярное выражение, которое соответствует внутреннему консольно-пар первого, так что порядок, в котором preg_match_all находит соответствующая скобку-пары должны быть:

[abc] 
[def] 
[test[abc][def]] 
[foo[test[abc][def]]bar] 

Все тексты могут различаться.

Возможно ли это с помощью preg_match_all?

+0

Возможный дубликат [Вложенные круглые скобки в массив с использованием регулярного выражения в PHP] (http://stackoverflow.com/questions/10361562/nested-parentheses-to-array-using-regex-in-php) –

+0

Может ли когда-либо быть более одной пары внутри другой пары? например '[Foo [бар] [Баз] [XYZZY] лол]'? – leftclickben

+0

Да, в идеале это может быть так. Я изменил вопрос, включив эту функциональность ... – Dylan

ответ

2

Это невозможно с регулярными выражениями. Независимо от того, насколько сложно ваше регулярное выражение, оно всегда будет возвращать самое первое совпадение.

В лучшем случае вам нужно будет использовать несколько регулярных выражений, но даже тогда у вас будут проблемы, поскольку регулярные выражения не могут действительно подсчитывать соответствующие скобки. Лучше всего проанализировать эту строку другим способом.

0

В вашем вопросе не видно, какую «структуру совпадений» вы хотите ... Но вы можете использовать только простые массивы. Попробуйте

preg_match_all('#\[([a-z\)\(]+?)\]#',$original,$m); 

, что для $original = 'bar[foo[test[abc][def]]bar]foo' возвращает массив с "ABC" и "DEF", внутренних.


Для вашего вывода вам нужен цикл для «задачи синтаксического анализа». PCRE с preg_replace_callback лучше для синтаксического анализа.

Возможно, этот цикл является хорошей подсказкой для вашей проблемы,

$original = 'bar[foo[test[abc][def]]bar]foo'; 

for($aux=$oldAux=$original; 
     $oldAux!=($aux=printInnerBracket($aux)); 
     $oldAux=$aux 
); 
print "\n-- $aux"; 

function printInnerBracket($s) { 
    return preg_replace_callback(
      '#\[([a-z\)\(]+?)\]#', // the only one regular expression 
      function($m) { 
       print "\n$m[0]"; 
       return "($m[1])"; 
      }, 
      $s 
    ); 
} 

Результат (обратный вызов для печати):

[abc] 
[def] 
[test(abc)(def)] 
[foo(test(abc)(def))bar] 
-- bar(foo(test(abc)(def))bar)foo 

Смотрите также this related question.