为什么 re.sub() 在 Python 中默认添加不匹配的字符串?

Why re.sub() adds not matched string by default in Python?

import re

print(re.sub(
    r'(size:)\D+(\d+)\D+(\d+)\D+(\d+)',
    r'xx',
    'START, size: 100Х200 x 50, END'
))

输出:

'START, 100x200x50, END'

我不希望正则表达式中没有提到的字符串部分。外面的一切 — 必须省略。

是的,如果我们通过在末尾和开头添加 .* 来提及整个内容,它将按预期工作:

r'.*(size:)\D+(\d+)\D+(\d+)\D+(\d+).*'

输出将是:

'100x200x50'

...默认情况下(对我而言)。

为什么? =)

更新

是的,很明显,它正在寻找一个匹配项来替换它。 (半夜加班不会太明显=D)

但是最好有解决方案来避免匹配整个字符串。

re.sub替换匹配的部分,不匹配的部分保持不变是正常的。

您应该尝试匹配所有内容:

import re
print(re.sub(
    r'.*(size:)\D+(\d+)\D+(\d+)\D+(\d+).*',
    r'xx',
    'START, size: 100Х200 x 50, END'
))

输出:100x200x50

选择:re.search
import re
m = re.search(
    r'size:\D+(\d+)\D+(\d+)\D+(\d+)',
    'START, size: 100Х200 x 50, END'
)
print('x'.join(m.groups()) if m else 'no match')

你好像对sub的作用有误解。它替换匹配的正则表达式。此正则表达式 r'(size:)\D+(\d+)\D+(\d+)\D+(\d+)' 匹配您的字符串的一部分,因此只有匹配的部分将被替换,捕获组不会影响这一点。 你可以做什么(如果你不想在开头和结尾添加 .* 就是像这样使用 re.findall

re.findall(
    r'(size:)\D+(\d+)\D+(\d+)\D+(\d+)',
    'START, size: 100Х200 x 50, END'
    )

这将 return [('size:', '100', '200', '50')],然后您可以根据需要对其进行格式化。 一种方法是作为一个没有错误处理的班轮是这样的:

'{1}x{2}x{3}'.format(
    *re.findall(
        r'(size:)\D+(\d+)\D+(\d+)\D+(\d+)',
        'START, size: 100Х200 x 50, END')[0]
    )