Python 正则表达式:为什么 re.sub('a*', '-', 'abxd',count=1) = '-bxd'?不应该是“-abxd”吗?
Python regex: Why re.sub('a*', '-', 'abxd',count=1) = '-bxd' ? Shouldn't it be '-abxd'?
阅读 python 的 re
包的文档后。我认为结果应该是 re.sub('a*', '-', 'abxd',count=1) -> '-abxd'
。但是,我得到以下结果:
re.sub('a*', '-', 'abxd',count=1) -> '-bxd'
我真的很困惑,因为第一个匹配应该是 'abxd'
中 'a'
前面的空匹配。
特别是,我尝试了其他三个示例,得到了如下预期结果:
re.sub('a*', '-', ' abxd',count=1) -> '- abxd'
re.sub('a*', '-', ' abxd',count=1) -> '- abxd'
re.sub('x*', '-', ' abxd',count=1) -> '-abxd'
非常感谢您的帮助。
a*
在当前位置匹配 尽可能多的 个 a
副本。它可以匹配零(不像a+
),但如果有的话,它会匹配所有。
考虑一下 findall
对您的示例做了什么:
>>> re.findall(r'(a*)', 'abcd')
['a', '', '', '', '']
五个匹配项,第一个是最简单和最明显的:匹配 a
。下一个是 0 or more 匹配每个字符边界:
for i in range(len(re.findall(r'a*', 'abcd'))):
s_sub=re.sub(r'a*', '-', 'abcd', count=i+1)
print(f' sub {i+1}: {s_sub}')
打印:
sub 1: -bcd
sub 2: --bcd
sub 3: --b-cd
sub 4: --b-c-d
sub 5: --b-c-d-
如果你仔细想想,这才是正确的做法。
如果你有re.sub('a*', '-', 'aaaabxd',count=1)
,你会期望:
- 第一个匹配是在字符串开头的字符边界插入
-
得到'-aaabxd'
或
- 在
a
之后得到 'aaa-bxd'
或
- 您是否认为
a*
意味着尽可能多的 a 导致 '-bxd'
?
第三个选项是 a*
:
>>> re.sub('a*', '-', 'aaaabxd',count=1)
'-bxd'
此行为是 quantifier *
贪婪的结果。
正则表达式语言中有一个元字符表示 不要贪婪,当与 +
或 *
量词组合时 是 LAZY[=30] =].如果您使用它,它会导致您期望的行为,因为匹配所有 a
的第一个明显匹配被跳过:
>>> re.sub('a*?', '-', 'aaaabxd',count=1)
'-aaaabxd'
并且:
s='aabcd'
for i in range(len(re.findall(r'a*?', s))):
s_sub=re.sub(r'a*?', '-', s, count=i+1)
print(f'sub {i+1}: {s_sub}')
打印:
sub 1: -aabcd
sub 2: --abcd
sub 3: ---abcd
sub 4: ----bcd
sub 5: -----bcd
sub 6: -----b-cd
sub 7: -----b-c-d
sub 8: -----b-c-d-
阅读 python 的 re
包的文档后。我认为结果应该是 re.sub('a*', '-', 'abxd',count=1) -> '-abxd'
。但是,我得到以下结果:
re.sub('a*', '-', 'abxd',count=1) -> '-bxd'
我真的很困惑,因为第一个匹配应该是 'abxd'
中 'a'
前面的空匹配。
特别是,我尝试了其他三个示例,得到了如下预期结果:
re.sub('a*', '-', ' abxd',count=1) -> '- abxd'
re.sub('a*', '-', ' abxd',count=1) -> '- abxd'
re.sub('x*', '-', ' abxd',count=1) -> '-abxd'
非常感谢您的帮助。
a*
在当前位置匹配 尽可能多的 个 a
副本。它可以匹配零(不像a+
),但如果有的话,它会匹配所有。
考虑一下 findall
对您的示例做了什么:
>>> re.findall(r'(a*)', 'abcd')
['a', '', '', '', '']
五个匹配项,第一个是最简单和最明显的:匹配 a
。下一个是 0 or more 匹配每个字符边界:
for i in range(len(re.findall(r'a*', 'abcd'))):
s_sub=re.sub(r'a*', '-', 'abcd', count=i+1)
print(f' sub {i+1}: {s_sub}')
打印:
sub 1: -bcd
sub 2: --bcd
sub 3: --b-cd
sub 4: --b-c-d
sub 5: --b-c-d-
如果你仔细想想,这才是正确的做法。
如果你有re.sub('a*', '-', 'aaaabxd',count=1)
,你会期望:
- 第一个匹配是在字符串开头的字符边界插入
-
得到'-aaabxd'
或 - 在
a
之后得到'aaa-bxd'
或 - 您是否认为
a*
意味着尽可能多的 a 导致'-bxd'
?
第三个选项是 a*
:
>>> re.sub('a*', '-', 'aaaabxd',count=1)
'-bxd'
此行为是 quantifier *
贪婪的结果。
正则表达式语言中有一个元字符表示 不要贪婪,当与 +
或 *
量词组合时 是 LAZY[=30] =].如果您使用它,它会导致您期望的行为,因为匹配所有 a
的第一个明显匹配被跳过:
>>> re.sub('a*?', '-', 'aaaabxd',count=1)
'-aaaabxd'
并且:
s='aabcd'
for i in range(len(re.findall(r'a*?', s))):
s_sub=re.sub(r'a*?', '-', s, count=i+1)
print(f'sub {i+1}: {s_sub}')
打印:
sub 1: -aabcd
sub 2: --abcd
sub 3: ---abcd
sub 4: ----bcd
sub 5: -----bcd
sub 6: -----b-cd
sub 7: -----b-c-d
sub 8: -----b-c-d-