PHP, регулярное выражение и многоуровневые фигурные скобки

У меня есть строка, состоящая из нескольких предложений, заключенных в фигурные скобки, которые я хочу удалить. Это было бы не так сложно сделать (как я знаю сейчас), но настоящая проблема в том, что он многоуровневый, и все, что я хочу, это убрать скобки верхнего уровня и оставить все внутри нетронутым. Это выглядит примерно так:

{Super duper {extra} text.} {Which I'm really {starting to} hate!} {But I {won't give up} so {easy}!} {Especially when someone is {gonna help me}.}

Я хочу создать массив, который будет состоять из этих четырех записей:

Super duper {extra} text.
Which I'm really {starting to} hate!
But I {won't give up} so {easy}!
Especially when someone is {gonna help me}.

Я пробовал два способа, одним из которых был preg_split, который не принес много пользы:

$key = preg_split('/([!?.]{1,3}\} \{)/',$key, -1, PREG_SPLIT_DELIM_CAPTURE);
$sentences = array();

for ($i=0, $n=count($key)-1; $i<$n; $i+=2) {
$sentences[] = $key[$i].$key[$i+1]."<br><br>";
}

Другой использовал preg_match_all, который был довольно хорош, пока я не понял, что эти скобки многоуровневые:

$matches = array();
$key = preg_match_all('/\{[^}]+\}/', $key, $matches);
$key = $matches[0];

Заранее спасибо! :)


person moskalak    schedule 13.06.2012    source источник
comment
Ваши фигурные скобки гарантированно сбалансированы?   -  person ghoti    schedule 14.06.2012
comment
@ghoti Да, они гарантированно сбалансированы.   -  person moskalak    schedule 14.06.2012
comment
@Vulcan Я добавил информацию о том, что я пробовал, в исходный пост.   -  person moskalak    schedule 14.06.2012
comment
Всегда ли фигурные скобки верхнего уровня разделяются одним пробелом?   -  person nickb    schedule 14.06.2012


Ответы (2)


Вы можете использовать рекурсивное выражение следующим образом:

/{((?:[^{}]++|(?R))*+)}/

Желаемые результаты будут в первой группе захвата.

Использование, что-то вроде:

preg_match_all('/{((?:[^{}]++|(?R))*+)}/', $str, $matches);
$result = $matches[1];
person Qtax    schedule 13.06.2012
comment
Редактировать: это работает, и я понял, большое спасибо, сэр! Теперь мне нужно только понять, что именно делает это регулярное выражение. :) - person moskalak; 14.06.2012
comment
@moskalak, элементы в $matches[1]. Также добро пожаловать в SO, здесь лучший способ поблагодарить — проголосовать. ;-) - person Qtax; 14.06.2012

$x="foo {bar {baz}} whee";
$re="/(^[^{]*){(.*)}([^}]*)$/";
print preg_replace($re, "\\1\\2\\3", $x) . "\n";'

возвращает:

foo bar {baz} whee
person ghoti    schedule 13.06.2012
comment
Спасибо за это предложение. Было бы здорово, но он возвращает строку, лишенную квадратных скобок верхнего уровня, а мне действительно нужно создать массив, в котором каждая строка, заключенная в квадратные скобки верхнего уровня, будет еще одной записью. - person moskalak; 14.06.2012