使用替换函数时,为什么反向引用不能在Python的re.sub中工作?

时间:2012-10-18 16:04:52

标签: python regex python-2.7

在Python 2.7中使用re.sub,以下示例使用简单的反向引用:

re.sub('-{1,2}', r'\g<0> ', 'pro----gram-files')

按预期输出以下字符串:

'pro-- -- gram- files'

我希望以下示例相同,但不是:

def dashrepl(matchobj):
    return r'\g<0> '
re.sub('-{1,2}', dashrepl, 'pro----gram-files')

这会产生以下意外输出:

'pro\\g<0> \\g<0> gram\\g<0> files'

为什么这两个例子给出不同的输出?我是否遗漏了解释此问题的文档?这种行为是否比我预期的更好?有没有办法在替换函数中使用反向引用?

2 个答案:

答案 0 :(得分:5)

由于有更简单的方法可以实现您的目标,您可以使用它们。

正如您已经看到的,您的替换函数会获取匹配对象作为参数。

除其他外,此对象具有可以替代使用的方法group()

def dashrepl(matchobj):
    return matchobj.group(0) + ' '

将准确提供您的结果。


但你完全正确 - the docs以这种方式有点混乱:

他们描述了repl参数:

  

repl可以是字符串或函数;如果它是一个字符串,则处理它中的任何反斜杠转义。

  

如果repl是一个函数,则会针对模式的每个非重叠事件调用它。该函数接受一个匹配对象参数,并返回替换字符串。

可以解释这个,就好像函数返回的“替换字符串”也适用于反斜杠转义的处理。

但由于此处理仅针对“它是一个字符串”的情况进行描述,因此它变得更清晰,但乍一看并不明显。

答案 1 :(得分:3)

如果将函数传递给re.sub,它允许您将匹配替换为从函数返回的字符串。基本上,re.sub使用不同的代码路径,具体取决于您是传递函数还是字符串。是的,这实际上是可取的。考虑一下您要将foobar的匹配以及bazqux的匹配替换的情况。然后你可以把它写成:

repdict = {'foo':'bar','baz':'qux'}
re.sub('foo|baz',lambda match: repdict[match.group(0)],'foo')

您可以争辩说,您可以在2次通过中执行此操作,但如果repdict看起来像{'foo':'baz','baz':'qux'}

,则无法执行此操作

我认为你不能用反向引用来做到这一点(至少不容易)。