正则表达式 - 替换匹配的子组

时间:2014-01-09 15:17:50

标签: python regex

以下代码在字符串中查找要替换的组的正则表达式的名称。我想使用它来分别将名称name_1name_2not_escaped更改为test_name_1test_name_2test_not_escaped。在匹配m中,每个名称等于m.group(2)。我怎样才能做到这一点 ?

p = re.compile(r"(?<!\\)(\\\\)*\\g<([a-zA-Z_][a-zA-Z\d_]*)>")

text = r"</\g<name_1>\g<name_2>\\\\\g<not_escaped>\\g<escaped>>>"

for m in p.finditer(text):
    print(
        '---',
        m.group(),
        m.group(2)
    )

这给出了以下输出。

---
\g<name_1>
name_1

---
\g<name_2>
name_2

---
\\\\\g<not_escaped>
not_escaped

2 个答案:

答案 0 :(得分:1)

您需要使用\<digit>反向引用重现整个组0文本,以重新使用捕获的组:

p.sub(r'\1\\g<test_\2>', text)

此处\1表示初始反斜杠组,\2表示名称前缀为test_

要实现此目的,您需要将* 移动到第一个捕获组,以确保捕获的组不匹配:

p = re.compile(r"(?<!\\)((?:\\\\)*)\\g<([a-zA-Z_][a-zA-Z\d_]*)>")

我使用非捕获组((?:...))来保持反斜杠组合在一起。

演示:

>>> text = r"</\g<name_1>\g<name_2>\\\\\g<not_escaped>\\g<escaped>>>"
>>> p = re.compile(r"(?<!\\)((?:\\\\)*)\\g<([a-zA-Z_][a-zA-Z\d_]*)>")
>>> print(p.sub(r'\1\\g<test_\2>', text))
</\g<test_name_1>\g<test_name_2>\\\\\g<test_not_escaped>\\g<escaped>>>

答案 1 :(得分:0)

实现此目的的最简单方法是使用一系列对str.replace的三个简单调用,而不是使用正则表达式进行替换:

import re

p = re.compile(r"(?<!\\)(\\\\)*\\g<([a-zA-Z_][a-zA-Z\d_]*)>")

text = r"</\g<name_1>\g<name_2>\\\\\g<not_escaped>\\g<escaped>>>"

for m in p.finditer(text):
    if m.groups(2):
        replacement = m.groups(2)[1]
        text = text.replace(replacement, 'test_' + replacement)