RegExp в PHP. Получить текст между круглыми скобками первого уровня

У меня есть два типа строк в одном тексте:

a(bc)de(fg)h

а(бкд(эф)г)ч

Мне нужно получить текст между круглыми скобками первого уровня. В моем примере это:

bc

fg

bcd(ef)g

Я попытался использовать следующее регулярное выражение /\((.+)\)/ с флагом Ungreedy (U):

bc

fg

bcd (эф

И без него:

bc)de(fg

bcd(ef)g

Оба варианта не делают то, что мне нужно. Может кто знает как решить мою проблему?


person andreyb1990    schedule 08.04.2017    source источник
comment
почему регекс? Простая итерация по строке будет работать   -  person frank    schedule 08.04.2017
comment
вы пытаетесь обрабатывать каждую строку отдельно ИЛИ они являются частью произвольного текста?   -  person RomanPerekhrest    schedule 08.04.2017
comment
Эти строки являются частью одного текста.   -  person andreyb1990    schedule 08.04.2017


Ответы (3)


На этот вопрос в значительной степени есть ответ, но реализации немного неоднозначны. Вы можете использовать логику в принятом ответе без ~s, чтобы получить это регулярное выражение:

\(((?:\[^\(\)\]++|(?R))*)\)

Проверено с такими выводами:

введите здесь описание изображения

person Robin Mackenzie    schedule 08.04.2017

Используйте рекурсивный шаблон em> для соответствия подстрокам во вложенных скобках:

$str = "a(bc)de(fg)h some text a(bcd(ef)g)h ";
preg_match_all("/\((((?>[^()]+)|(?R))*)\)/", $str, $m);

print_r($m[1]);

Выход:

Array
(
    [0] => bc
    [1] => fg
    [2] => bcd(ef)g
)

\( ( (?>[^()]+) | (?R) )* \)

Сначала он соответствует открывающей скобке. Затем он соответствует любому количеству подстрок, которые могут быть либо последовательностью без круглых скобок, либо рекурсивным совпадением самого шаблона (т. е. правильно заключенной в круглые скобки подстроки). В конце есть закрывающая скобка.


Технические предупреждения:

Если в шаблоне более 15 захватывающих скобок, PCRE должен получить дополнительную память для хранения данных во время рекурсии, что он делает с помощью pcre_malloc, освобождая ее с помощью pcre_free. после. Если память не может быть получена, он сохраняет данные только для первых 15 скобок захвата, так как нет способа выдать ошибку нехватки памяти из рекурсии.

person RomanPerekhrest    schedule 08.04.2017
comment
Как здесь сопоставить второй уровень, т.е. ef (из любопытства)? +1 в любом случае. - person Jan; 08.04.2017
comment
@Jan, (ef) становится рекурсивным совпадением самого шаблона (т.е. родительского шаблона) - person RomanPerekhrest; 09.04.2017

Пожалуйста, вы можете попробовать это:

preg_match("/\((.+)\)/", $input_line, $output_array);

Протестируйте этот код на http://www.phpliveregex.com/.

Regex: \((.+)\)
Input: a(bcd(eaerga(er)gaergf)g)h
Output: array(2
   0    =>  (bcd(eaerga(er)gaergf)g)
   1    =>  bcd(eaerga(er)gaergf)g
)
person kodmanyagha    schedule 08.04.2017