【问题标题】:Why don't backreferences work in Python's re.sub when using a replacement function?为什么使用替换函数时,反向引用在 Python 的 re.sub 中不起作用?
【发布时间】:2012-10-09 03:54:29
【问题描述】:

在 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'

为什么这两个示例给出不同的输出?我是否错过了解释这一点的文档中的某些内容?有什么特别的原因表明这种行为比我预期的更可取吗?有没有办法在替换函数中使用反向引用?

【问题讨论】:

    标签: python regex python-2.7


    【解决方案1】:

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

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

    这个对象有一个方法group(),可以用来代替:

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

    这将给出你的结果。


    但你是完全正确的 - the docs 这样有点混乱:

    他们描述了repl 参数:

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

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

    可以将此解释为函数返回的“替换字符串”也适用于反斜杠转义的处理。

    但是由于这个处理只针对“它是一个字符串”的情况来描述,它变得更加清晰,但乍一看并不明显。

    【讨论】:

      【解决方案2】:

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

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

      您可以争辩说您可以在 2 次通过中完成此操作,但如果 repdict 看起来像 {'foo':'baz','baz':'qux'},则您不能这样做

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

      【讨论】:

      • 您可以轻松地从匹配对象中获取整个字符串或单个组,但是如何获取不在组中的部分字符串?例如,如果正则表达式类似于“begin.*?(groupstart.*?groupstop).*?end”,那么如何获得与反向引用相同的功能?
      • @amcnabb -- 我不知道(我通常不使用反向引用)。这里的事情是你有两个选择。开心就好:)。在某些情况下,您可以使用任一选项进行相同的操作。在其他情况下,可能只有 2 个中的一个会起作用。
      • @amcnabb 反向引用总是指给定的组。在您的示例中,您使用match.group(1) 获得您的组。
      • @glglgl -- 谢谢,我没有完全理解 amcnabb 提出的问题,但有了你的回答,我明白了。
      • +glglgl,你是对的,我不知道为什么我在那里感到困惑。
      猜你喜欢
      • 2014-01-12
      • 1970-01-01
      • 2021-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-17
      • 2015-12-08
      • 2016-05-21
      相关资源
      最近更新 更多