re.sub('a(b)','d','abc')
产生 dc
,而不是 adc
。
为什么
re.sub
替换整个捕获组,而不是仅捕获组'(b)'?
因为它应该替换整个出现的模式:
返回通过用替换 repl 替换 string 中最左边不重叠的模式而获得的字符串。
如果仅替换某些子组,则具有多个组的复杂正则表达式将无法工作。有几种可能的解决方案:
re.sub('ab', 'ad', 'abc')
- 我最喜欢的,因为它非常易读且明确。re.sub('(a)b', r'\1d', 'abc')
repl
参数,并使其处理 Match
对象并返回所需的结果。re.sub('(?<=a)b', r'd', 'abxb')
产生adxb
。该组开头的 ?<=
表示“这是一个前瞻”。我知道这并不是严格回答OP问题,但是这个问题很难用谷歌搜索(充斥着解释......)
对于那些像我一样来到这里的人,因为他们想实际用字符串替换不是第一个的捕获组,而不需要对字符串或正则表达式有特殊的了解:
#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 无法指定它应该替换的实际捕获组...
因为这正是
re.sub()
文档告诉你它应该做的:
'a(b)'
表示“匹配'a',带有可选的尾随'b'”。 (它可以单独匹配“a”,但它不可能像您预期的那样单独匹配“b”。如果您是这个意思,请使用非贪婪的 (a)??b
)。如果你想要你想要的输出,你需要在
'(a)??'
上进行非贪婪匹配:
>>> re.sub('(a)??b','d','abc')
'dc'
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)
)
如上所述,首先我们编译一个带有不区分大小写标志的正则表达式模式。
然后我们检查文本是否与模式匹配,如果匹配,我们引用正则表达式模式(年龄)中唯一带有组号的组。