[英]Why does re.findall() find more matches than re.sub()?
考虑以下:
>>> import re
>>> a = "first:second"
>>> re.findall("[^:]*", a)
['first', '', 'second', '']
>>> re.sub("[^:]*", r"(\g<0>)", a)
'(first):(second)'
re.sub()
的行为最初更有意义,但我也能理解re.findall()
的行为。 毕竟,你可以匹配first
和first
一个之间的空字符串:
它只包含非冒号字符(正好是零),但为什么re.sub()
行为方式不同?
不应该是最后一个命令的结果是(first)():(second)()
?
你使用允许空匹配的*:
'first' -> matched
':' -> not in the character class but, as the pattern can be empty due
to the *, an empty string is matched -->''
'second' -> matched
'$' -> can contain an empty string before,
an empty string is matched -->''
引用re.findall()
的文档 :
结果中包含空匹配,除非它们触及另一个匹配的开头。
您在子结果中看不到空匹配的原因在re.sub()
的文档中进行了解释:
仅当与前一个匹配不相邻时,才会替换模式的空匹配。
尝试这个:
re.sub('(?:Choucroute garnie)*', '#', 'ornithorynque')
现在这个:
print re.sub('(?:nithorynque)*', '#', 'ornithorynque')
没有连续的#
由于某种原因,处理空匹配的算法是不同的。
在findall
的情况下,它的工作方式类似于(优化版本):对于每个可能的起始索引0 <= i <= len(a),如果字符串在i处匹配,则追加匹配; 并且通过使用此规则避免重叠结果:如果在i处存在长度为m的匹配,则不要在i + m之前查找下一个匹配项。 你的例子返回['first', '', 'second', '']
是在first
和second
之后立即找到空匹配,但不是在冒号之后找到 - 因为从那个位置开始寻找一个匹配返回完整的字符串second
。
在sub
的情况下,正如您所注意到的那样,区别在于它明确忽略了在另一个匹配之后立即发生的长度为0的匹配。 虽然我明白为什么这可能有助于避免出现意外行为sub
,我不确定为什么会存在这种差异(例如,为什么不findall
使用相同的规则)。
import re
a = "first:second:three"
print re.findall("[^:]*", a)
返回匹配模式的所有子字符串,这里给出
>>>
['first', '', 'second', '', 'three', '']
sub()
用于替换,并将替换最左边的非重叠模式。 前
import re
a = "first:second:three"
print re.sub("[^:]*", r"smile", a)
给
>>>
smile:smile:smile
您可以使用第4个arg命令要替换的出现次数,count:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.