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

2024-04-23 23:38:38 发布

您现在位置:Python中文网/ 问答频道 /正文

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

为什么re.sub要取代整个捕获组,而不仅仅是捕获组'(b)'?


Tags: redcabcadc
3条回答

因为它应该取代整个模式的出现:

Return the string obtained by replacing the leftmost non-overlapping occurrences of the pattern in string by the replacement 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。小组开头的?<=说“这是一个展望”。

因为这正是re.sub()doc告诉你的:

  • 模式'a(b)'表示“匹配‘a’,带有可选的尾随‘b’”。(它可以自己匹配“a”,但它不可能像你想象的那样自己匹配“b”。如果你是这个意思,那么使用非贪婪的(a)??b)。
  • 替换字符串是'd'
  • 因此,在字符串“abc”上,它匹配所有“ab”,并用“d”替换,因此结果是“dc”

如果你想要你想要的输出,你需要在'(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)
    )

如上所述,首先我们编译一个带有不区分大小写标志的regex模式。

然后我们检查文本是否与模式匹配,如果匹配,我们将引用regex模式(age)中唯一的组(组号为1)。

相关问题 更多 >