重新上传捕获组

时间:2017-02-08 04:10:27

标签: python python-3.x

re.sub('a(b)','d','abc')会产生dc,而非adc。那么为什么re.sub不理解这里的捕获组呢?

4 个答案:

答案 0 :(得分:9)

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

  

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

如果只替换某个子组,那么具有多个组的复杂正则表达式将不起作用。有几种可能的解决方案:

  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')会产生adxb。小组开头的?<=说“这是一个先行”。

答案 1 :(得分:0)

import re

pattern = re.compile(r"I am (\d{1,2}) .*", re.IGNORECASE)

text = "i am 32 years old"

if re.match(pattern, text):
    print(
        re.sub(pattern, r"Your are \1 years old.", text, count=1)
    )

如上所述,首先我们使用不区分大小写的标志编译正则表达式模式。

然后我们检查文本是否与模式匹配,如果匹配,我们引用正则表达式(年龄)中唯一具有组号\ 1的组。

答案 2 :(得分:0)

因为这正是re.sub()文档告诉您的事情:

  • 模式'a(b)'表示“匹配'a',带有可选的结尾'b'”。 (它可以单独匹配“ a”,但是不可能像您期望的那样单独匹配“ b”。如果您要这样做,请使用非贪婪的(a)??b)。< / li>
  • 替换字符串为'd'
  • 因此在字符串“ abc”上,它匹配所有“ ab”并将其替换为“ d”,因此结果是“ dc”

如果要获得所需的输出,则需要在'(a)??'上进行非贪心匹配:

>>> re.sub('(a)??b','d','abc')
'dc'

答案 3 :(得分:0)

我知道这不是严格回答 OP 问题,但是这个问题可能很难用 google 搜索(被 \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 不能指定它应该替换的实际捕获组...