Замена повторных захватов
Ниже приведено описание Regex Python - Заменить одиночные кавычки и скобки.
Задача:
Примеры входных строк:
RSQ(name['BAKD DK'], name['A DKJ'])
SMT(name['BAKD DK'], name['A DKJ'], name[ QRT'])
Требуемые выходы:
XYZ(BAKD DK, A DKJ)
XYZ(BAKD DK, A DKJ, S QRT)
Число name['something']
-подобных элементов является переменной.
Текущее решение:
В настоящее время я делаю это через два отдельных вызова re.sub()
:
>>> import re
>>>
>>> s = "RSQ(name['BAKD DK'], name['A DKJ'])"
>>> s1 = re.sub(r"^(\w+)", "XYZ", s)
>>> re.sub(r"name\['(.*?)'\]", r"\1", s1)
'XYZ(BAKD DK, A DKJ)'
Вопрос:
Можно ли объединить эти два вызова re.sub()
в один?
Другими словами, я хочу что-то заменить в начале строки, а затем несколько подобных вещей после, все это за один раз.
Я просмотрел regex
модуль - это способность захватить повторяющиеся шаблоны выглядит очень многообещающим, пробовал использовать regex.subf()
, но не смог заставить его работать.
Ответы
Ответ 1
Вы действительно можете использовать модуль регулярных выражений и повторные записи. Основной интерес состоит в том, что вы можете проверить структуру согласованной строки:
import regex
regO = regex.compile(r'''
\w+ \( (?: name\['([^']*)'] (?: ,[ ] | (?=\)) ) )* \)
''', regex.VERBOSE);
regO.sub(lambda m: 'XYZ(' + (', '.join(m.captures(1))) + ')', s)
(Обратите внимание, что вы можете заменить "name"
на \w+
или что угодно, без проблем.)
Ответ 2
Вы можете это сделать. Хотя я не думаю, что это очень читаемо. И сделать это таким образом может стать непоколебимым, если вы начнете добавлять больше шаблонов для замены. Он использует тот факт, что строка замены также может быть функцией.
s = "RSQ(name['BAKD DK'], name['A DKJ'])"
re.sub(r"^(\w+)|name\['(.*?)'\]", lambda m: 'XYZ' if m.group(1) else m.group(2), s)
Ответ 3
Пожалуйста, не делайте этого в любом коде, который мне нужно поддерживать.
Вы пытаетесь разобрать синтаксически корректный Python. Для этого используйте ast
. Это более читаемо, проще распространяться на новый синтаксис и не разваливаться на какой-то странный угловой случай.
Рабочий пример:
from ast import parse
l = [
"RSQ(name['BAKD DK'], name['A DKJ'])",
"SMT(name['BAKD DK'], name['A DKJ'], name[ QRT'])"
]
for item in l:
tree = parse(item)
args = [arg.slice.value.s for arg in tree.body[0].value.args]
output = "XYZ({})".format(", ".join(args))
print(output)
Печать
XYZ(BAKD DK, A DKJ)
XYZ(BAKD DK, A DKJ, S QRT)
Ответ 4
Вы можете использовать re.findall()
и простое форматирование строки:
>>> s = "SMT(name['BAKD DK'], name['A DKJ'], name[ QRT'])"
>>>
>>> 'XYZ({})'.format(','.join(re.findall(r"'([^']+)'", s)))
'XYZ(BAKD DK,A DKJ,S QRT)'