Python 正则表达式 - 用括号内的内容替换括号中的文本

4

我正在尝试编写一个Python函数,它可以将用花括号包围的文本实例替换为括号内的内容,同时保留空括号对。例如:

foo {} bar {baz} 将变成 foo {} bar baz

我创建的匹配模式是 {[^{}]+},即一些不包含花括号的文本(以防止重叠匹配)被一组花括号包围。

明显的解决方案是使用 re.sub 函数与我的模式进行匹配,并且我发现我可以使用 \g<0> 引用已匹配的文本:

>>> re.sub("{[^{}]+}", "A \g<0> B", "foo {} bar {baz}")
'foo {} bar A {baz} B'

那么这没有问题。然而,我卡在如何从引用文本中裁剪括号的问题上。如果我尝试将范围应用于替换字符串:

>>> re.sub("{[^{}]+}", "\g<0>"[1:-1], "foo{}bar{baz}")
'foo{}barg<0'

\g<0> 解析为匹配文本之前,会应用范围并修剪前导的 \ 和尾随的 >,只留下没有特殊含义的 g<0

我还尝试定义一个执行修剪操作的函数:

def trimBraces(string):
    return string[1:-1]

但是,毫不意外的是,这并没有改变任何事情。
>>> re.sub("{[^{}]+}", trimBraces("\g<0>"), "foo{}bar{baz}")
'foo{}barg<0'

这里我有什么遗漏吗?非常感谢您的帮助。
2个回答

4
您可以使用“捕获组”来替换匹配的一部分内容:
>>> re.sub(r"{([^{}]+)}", r"\1", "foo{}bar{baz}")
'foo{}barbaz'
>>> re.sub(r"{([^{}]+)}", r"\1", "foo {} bar {baz}")
'foo {} bar baz'

2
当您使用"\g<0>"[1:-1]作为替换模式时,您仅会切割"\g<0>"字符串,而不是此反向引用所指的实际值。
如果您需要使用您的“修剪”方法,您需要将匹配数据对象传递给re.sub函数:
re.sub("{[^{}]+}", lambda m: m.group()[1:-1], "foo{}bar{baz}")
# => foo{}barbaz

请看这个Python演示。注意,m.group()代表您的模式中的\g<0>,即整个匹配值。
然而,使用捕获组是一种更加“有机”的解决方案,请参见alexce的解决方案

1
感谢提供额外的信息。了解概念而非仅仅知道如何运作总是很有益的 :) - halbrd
1
请注意,当您想要从与更复杂的正则表达式模式(包含选择项)匹配的字符串中删除已知数量的字符时,此解决方案非常有效。这种方法可以很好地替代Python re库中缺失的分支重置功能。假设您需要匹配像"..."'...'[....](但不包括[..."'....")这样的子字符串,并将其替换为括号内的内容。在Python 2.x中,使用反向引用方法的re.sub函数会出现问题。而Python 3.5的re库可以处理这个问题。在Python 3.5.1中,执行print(re.sub(r'"([^"]*)"|\'([^\']*)\'', r'\1\2', "'Something'"))会打印出Something - Wiktor Stribiżew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接