Регулярное выражение Python: сопоставление скобок в скобках
Я пытался сопоставить следующую строку:
string = "TEMPLATES = ( ('index.html', 'home'), ('base.html', 'base'))"
Но, к сожалению, мое знание регулярных выражений очень ограничено, так как вы можете видеть, что есть две круглые скобки, которые нужно сопоставить, а также содержимое внутри второго
Я попытался использовать re.match("\(w*\)", string)
, но это не сработало, любая помощь будет принята с благодарностью.
Ответы
Ответ 1
Попробуйте следующее:
import re
w = "TEMPLATES = ( ('index.html', 'home'), ('base.html', 'base'))"
# find outer parens
outer = re.compile("\((.+)\)")
m = outer.search(w)
inner_str = m.group(1)
# find inner pairs
innerre = re.compile("\('([^']+)', '([^']+)'\)")
results = innerre.findall(inner_str)
for x,y in results:
print("%s <-> %s" % (x,y))
Вывод:
index.html <-> home
base.html <-> base
Объяснение:
outer
соответствует первой группе скобок с помощью \(
и \)
; по умолчанию search
находит самое длинное совпадение, предоставляя нам самую внешнюю пару ( )
. Матч m
содержит именно то, что между этими внешними круглыми скобками; его содержимое соответствует бит .+
outer
.
innerre
соответствует точно одной из ваших пар ('a', 'b')
, снова используя \(
и \)
для соответствия родительским содержимым в вашей входной строке и используя две группы внутри ' '
, чтобы соответствовать строкам внутри эти одинарные кавычки.
Затем мы используем findall
(а не search
или match
), чтобы получить все соответствия для innerre
(а не только одного). На данный момент results
- это список пар, о чем свидетельствует цикл печати.
Обновление: Чтобы соответствовать всему, вы можете попробовать что-то вроде этого:
rx = re.compile("^TEMPLATES = \(.+\)")
rx.match(w)
Ответ 2
Прежде всего, использование \(
недостаточно для сопоставления скобок. Python обычно реагирует на некоторые escape-последовательности в своих строках, поэтому он интерпретирует \(
как простой (
. Вам нужно либо написать \\(
, либо использовать необработанную строку, например. r'\('
или r"\("
.
Во-вторых, когда вы используете re.match
, вы привязываете поиск регулярных выражений к началу строки. Если вы хотите найти шаблон в любом месте строки, используйте re.search
.
Как сказал Джозеф в своем ответе, не совсем ясно, что вы хотите найти. Например:
string = "TEMPLATES = ( ('index.html', 'home'), ('base.html', 'base'))"
print re.findall(r'\([^()]*\)', string)
будет печатать
["('index.html', 'home')", "('base.html', 'base')"]
EDIT:
Я исправлен, @phooji прав: экранирование в этом конкретном случае не имеет значения. Но re.match
vs. re.search
или re.findall
по-прежнему важны.
Ответ 3
Если ваши строки выглядят как действительный код Python, вы можете это сделать:
import ast
var, s = [part.strip() for part in
"TEMPLATES = ( ('index.html', 'home'), ('base.html', 'base'))".split('=')]
result= ast.literal_eval(s)
Ответ 4
Ваш образец ищет открытый параграф, за которым следует ноль или более буква w, за которым следует близкий пароль. Вероятно, вы захотите использовать \w вместо w, но это не будет работать в вашем случае в любом случае, потому что у вас есть символы без слова рядом с открытым парнем.
Я думаю, вам следует рассмотреть возможность разделения строки на запятые. Какова ваша конечная цель?
Ответ 5
Лучше всего использовать соответствующий модуль синтаксического анализа, например, пипарирование.