Regex: сопоставлять скобки как жадные, так и не жадные
Я использую модуль регулярных выражений Python, re
,
Мне нужно сопоставить что-либо внутри '(' ')' в этих двух фразах, но "не так жадно". Как это:
show the (name) of the (person)
calc the sqrt of (+ (* (2 4) 3))
Результат должен вернуться из фразы 1:
name
person
Результат должен вернуться из фразы 2:
+ (* (2 4) 3)
Проблема в том, что, чтобы соответствовать первой фразе, я использовал '\(.*?\)'
Это, на второй фразе, просто подходит + (* (2 4)
И используя '\(.*\)'
чтобы соответствовать второй фразе правильно, на первой фразе подходит (name) of the (person)
Какое регулярное выражение работает на обе фразы правильно?
4 ответа
Pyparsing позволяет легко писать простые одноразовые парсеры для таких вещей:
>>> text = """show the (name) of the (person)
...
... calc the sqrt of (+ (* (2 4) 3))"""
>>> import pyparsing
>>> for match in pyparsing.nestedExpr('(',')').searchString(text):
... print match[0]
...
['name']
['person']
['+', ['*', ['2', '4'], '3']]
Обратите внимание, что вложенные имена родителей были отброшены, а вложенный текст возвращен как вложенная структура.
Если вы хотите оригинальный текст для каждого бита в скобках, используйте модификатор originalTextFor:
>>> for match in pyparsing.originalTextFor(pyparsing.nestedExpr('(',')')).searchString(text):
... print match[0]
...
(name)
(person)
(+ (* (2 4) 3))
То, что вы пытаетесь сделать, выглядит как маневровый двор (на самом деле это похоже на LISP, так что, возможно, вам стоит проверить PyLisp). Нет необходимости использовать регулярные выражения для анализа таких выражений.
См. Статью " Маневровый двор" @ wikipedia и ее реализацию на Python.
Это соответствует всей необходимой информации:
(?:\()(.*?\){2})|(?:\()(.*?)(?:\))
Группа 1 = + (* (2 4) 3)
- Последний ")" можно удалить с помощью.strip(')')
Группа 2 = имя, человек
Пока скобки не являются вложенными, вы можете использовать ленивое регулярное выражение:
\(.*?\)
Хотя вы можете теоретически проанализировать ограниченное количество вложений в регулярном выражении, это очень сложно и не стоит усилий. Это гораздо проще сделать с помощью пользовательской функции Python. Смотрите этот ответ для хорошего объяснения.