请考虑以下事项:
>>> import re
>>> a = "first:second"
>>> re.findall("[^:]*", a)
['first', '', 'second', '']
>>> re.sub("[^:]*", r"(\g<0>)", a)
'(first):(second)'
re.sub()
的行为最初更有意义,但我也能理解re.findall()
的行为。毕竟,您可以匹配first
和:
之间的空字符串,该字符串仅由非冒号字符组成(恰好为零),但为什么re.sub()
的行为方式不同? ?
最后一个命令的结果不应该是(first)():(second)()
吗?
答案 0 :(得分:7)
你使用允许空匹配的*:
'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 -->''
引用documentation for re.findall()
:
中解释了您未在子结果中看到空匹配的原因结果中包含空匹配,除非它们触及另一场比赛的开头。
仅当与前一个匹配不相邻时,才会替换模式的空匹配。
试试这个:
re.sub('(?:Choucroute garnie)*', '#', 'ornithorynque')
现在这个:
print re.sub('(?:nithorynque)*', '#', 'ornithorynque')
没有连续的#
答案 1 :(得分:3)
由于某种原因,处理空匹配的算法是不同的。
在findall
的情况下,它的作用类似于(优化版本):对于每个可能的起始索引0&lt; = i&lt; = len(a),如果字符串在i匹配,则追加比赛;并且通过使用此规则避免重叠结果:如果在i处存在长度为m的匹配,则不要在i + m之前查找下一个匹配项。您的示例返回['first', '', 'second', '']
的原因是,在first
和second
之后立即找到空匹配,但不会在冒号后找到 - 因为从该位置开始查找匹配将返回完整字符串second
。
在sub
的情况下,正如您所注意到的那样,区别在于它明确忽略了在另一个匹配后立即发生的长度为0的匹配。虽然我知道为什么这可能有助于避免sub
的意外行为,但我不确定为什么存在这种差异(例如,为什么findall
不会使用相同的规则。)
答案 2 :(得分:1)
import re
a = "first:second:three"
print re.findall("[^:]*", a)
返回匹配pattern的所有子字符串,这里给出
>>>
['first', '', 'second', '', 'three', '']
sub()
用于替换,并将替换最左边的非重叠模式。前
import re
a = "first:second:three"
print re.sub("[^:]*", r"smile", a)
给出
>>>
smile:smile:smile
您可以使用第4个arg命令要替换的出现次数,count: