Подтвердить что ты не робот

Замена повторных захватов

Ниже приведено описание 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(), но не смог заставить его работать.

4b9b3361

Ответ 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)'