为什么 re.sub 会替换整个模式,而不仅仅是其中的一个捕获组?

新手上路,请多包涵

re.sub('a(b)','d','abc') 产量 dc ,而不是 adc

为什么 re.sub 替换了整个捕获组,而不只是捕获组’(b)‘?

原文由 Nick 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 817
2 个回答

因为它应该替换整个出现的模式:

返回通过用替换 repl 替换 string 中最左边的非重叠模式而获得的字符串。

如果它只替换一些子组,那么具有多个组的复杂正则表达式将无法工作。有几种可能的解决方案:

  1. 完整指定模式: re.sub('ab', 'ad', 'abc') 我最喜欢的,因为它非常易读和明确。
  2. 捕获 保留的组,然后在模式中引用它们(注意它应该是原始字符串以避免转义): re.sub('(a)b', r'\1d', 'abc')
  3. 与前面的选项类似:提供回调函数作为 repl 参数并使其处理 Match 对象并返回所需的结果。
  4. 使用 lookbehinds/lookaheds,它们不包含在匹配中,但会影响匹配: re.sub('(?<=a)b', r'd', 'abxb') yields adxb 。该组开头的 ?<= 说“这是一个前瞻”。

原文由 yeputons 发布,翻译遵循 CC BY-SA 3.0 许可协议

我知道这不是严格回答 OP 问题,但这个问题很难用谷歌搜索(被 \1 解释淹没……)

对于那些像我一样来到这里的人,因为他们想实际用字符串替换不是第一个的捕获组,而不需要对字符串或正则表达式有特殊了解:

 #find offset [start, end] of a captured group within string
r = regex.search(oldText).span(groupNb)
#slice the old string and insert replacementText in the middle
newText = oldText[:r[0]] + replacementText + oldText[r[1]:]

我知道这是想要的行为,但我仍然不明白为什么 re.sub 不能指定它应该替换的实际捕获组……

原文由 Mr Buisson 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题