如何将回调传递给 re.sub,但仍插入匹配捕获?

Sci*_*tas 7 python regex

考虑:

text = "abcdef"
pattern = "(b|e)cd(b|e)"

repl = [r"\1bla\2", r"\1blabla\2"]
text = re.sub(pattern, lambda m: random.choice(repl), text)
Run Code Online (Sandbox Code Playgroud)

我想用列表的条目随机替换匹配项repl。但是,当使用lambda m: random.choice(repl)作为一个回调,它不会取代\1\2其捕获更多的等等,返回"\1bla\2"为纯文本。

我试图查找re.py以了解他们如何在内部执行此操作,因此我可能能够调用相同的内部函数,但这似乎并不简单。

上面的示例返回a\1bla\2fa\1blabla\2fwhileabblaefabblablaef在我的情况下是有效的选项。

请注意,我使用的是一个函数,因为在有多个匹配项的情况下,例如text = "abcdef abcdef",它应该repl为每个匹配项随机选择一个替换项- 而不是对所有匹配项使用相同的替换项。

Mar*_*yer 8

如果您传递一个函数,您将失去反向引用的自动转义。你只需要得到匹配对象就可以完成工作。所以你可以:

在正则表达式中选择一个字符串而不是传递一个函数:

text = "abcdef"
pattern = "(b|e)cd(b|e)"

repl = [r"\1bla\2", r"\1blabla\2"]
re.sub(pattern, random.choice(repl), text)
# 'abblaef' or 'abblablaef'
Run Code Online (Sandbox Code Playgroud)

或者编写一个函数来处理匹配对象并允许更复杂的处理。您可以利用expand使用反向引用:

text = "abcdef abcdef"
pattern = "(b|e)cd(b|e)"

def repl(m):
    repl = [r"\1bla\2", r"\1blabla\2"]           
    return m.expand(random.choice(repl))


re.sub(pattern, repl, text)

# 'abblaef abblablaef' and variations
Run Code Online (Sandbox Code Playgroud)

当然,您可以将该函数放入 lambda 中:

repl = [r"\1bla\2", r"\1blabla\2"]
re.sub(pattern, lambda m: m.expand(random.choice(repl)), text)
Run Code Online (Sandbox Code Playgroud)