替换重复捕获

时间:2016-05-23 01:01:07

标签: python regex

这是Python regex - Replace single quotes and brackets主题的后续行动。

任务:

示例输入字符串:

RSQ(name['BAKD DK'], name['A DKJ'])
SMT(name['BAKD DK'], name['A DKJ'], name['S 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 module - capture repeated patterns看起来非常有前途,尝试使用regex.subf()但未能使其正常工作。

4 个答案:

答案 0 :(得分:13)

您确实可以使用正则表达式模块和重复捕获。主要的兴趣是你可以检查匹配字符串的结构:

import regex

regO = regex.compile(r'''
    \w+ \( (?: name\['([^']*)'] (?: ,[ ] | (?=\)) ) )* \)
    ''', regex.VERBOSE);

regO.sub(lambda m: 'XYZ(' + (', '.join(m.captures(1))) + ')', s)

(请注意,您可以将"name"替换为\w+或您想要的任何问题。)

答案 1 :(得分:9)

你可以这样做。虽然我觉得它不太可读。如果你开始添加更多模式来替换,那么这样做可能会变得难以驾驭。它利用了替换字符串也可以是一个函数的事实。

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)

答案 2 :(得分:9)

请不要在我必须维护的任何代码中执行此操作。

您正在尝试解析语法上有效的Python。请使用ast。它更易读,更容易扩展到新的语法,并且不会在一些奇怪的角落情况下崩溃。

工作样本:

from ast import parse

l = [
    "RSQ(name['BAKD DK'], name['A DKJ'])",
    "SMT(name['BAKD DK'], name['A DKJ'], name['S 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)

答案 3 :(得分:3)

您可以使用re.findall()和简单的字符串格式:

>>> s = "SMT(name['BAKD DK'], name['A DKJ'], name['S QRT'])"
>>> 
>>> 'XYZ({})'.format(','.join(re.findall(r"'([^']+)'", s)))
'XYZ(BAKD DK,A DKJ,S QRT)'