Python 很难理解RE.findall()在这里做什么

Python 很难理解RE.findall()在这里做什么,python,regex,Python,Regex,我正试图让我的手臂围绕着Python RE模块。然而,我很难理解为什么python3认为findall()有两个匹配项 >>>import re >>>re.match('\d{1,3}[-\s]?\d{1,3}[-\s]?\d{1,4}', '123-345--0987') <_sre.SRE_Match object; span=(0, 7), match='123-345'> >>>re.search('\d{1,3}[-\

我正试图让我的手臂围绕着Python RE模块。然而,我很难理解为什么python3认为findall()有两个匹配项

>>>import re
>>>re.match('\d{1,3}[-\s]?\d{1,3}[-\s]?\d{1,4}', '123-345--0987')
<_sre.SRE_Match object; span=(0, 7), match='123-345'>
>>>re.search('\d{1,3}[-\s]?\d{1,3}[-\s]?\d{1,4}', '123-345--0987')
<_sre.SRE_Match object; span=(0, 7), match='123-345'>
>>>re.findall('\d{1,3}[-\s]?\d{1,3}[-\s]?\d{1,4}', '123-345--0987')
['123-345', '0987']
>>重新导入
>>>重新匹配('\d{1,3}[-\s]?\d{1,3}[-\s]?\d{1,4}',123-345--0987')
>>>重新搜索('\d{1,3}[-\s]?\d{1,3}[-\s]?\d{1,4}',123-345--0987')
>>>关于findall('\d{1,3}[-\s]?\d{1,3}[-\s]?\d{1,4}',123-345--0987')
['123-345', '0987']
我本以为findall()调用与0987不匹配?我错过了什么

>>>re.findall('\d{1,3}[-\s]?\d{1,3}[-\s]?\d{1,4}', '123-345--0987')
['123-345', '0987']
为什么?

因为
\d{1,3}
贪婪地匹配从1到3的数字。因为它是贪婪的,所以它尝试匹配尽可能大的东西,所以,
123-345
被匹配,而下面的
--
由于双破折号而无法匹配。然后它尝试从剩余字符串中查找匹配项,因此
0987
得到了匹配-
“09”由\d{1,3}
匹配,
“8”由\d{1,3}
匹配,
“7”由\d{1,4}
匹配

123-345--0987   \d{1,3}
首先,
\d{1,3}
尝试贪婪地匹配所有三位数字。如果找不到三个数字,那么它将尝试匹配两个数字,然后匹配一个数字。因为上面的模式是贪婪的,所以它匹配
123
345
098

123-345--0987   \d{1,3}[-\s]?
然后它尝试匹配以下可选的
-
或空格。因此,
123-
345-
098
得到了匹配

123-345--0987   \d{1,3}[-\s]?\d{1,3}
它与
123-345
0987
匹配,第二个匹配额外的
7
,因为您定义的
\d{1,3}
匹配的数字范围为1到3(此处发生回溯)

[-\s]?
匹配可选的空格字符或破折号。现在它与
123-345-
匹配,
0987
保持原样。因为这个模式是可选的

123-345--0987   \d{1,3}[-\s]?\d{1,3}[-\s]?\d{1,4}

为了提供匹配,所有贪婪匹配的
123-345
返回一步,并且
123-345
中的
5
由最后一个
\d{1,4}
模式匹配。请注意,它会在先前匹配的
123-345-
中删除
-
,因为
5-
后面没有数字。现在,进行第二个匹配,即
0987
。我们已经得到了一个匹配,但是为了提供匹配,
\d{1,4}
匹配最后一个
7
,并且
\d{1,3}
模式在
[-\s]?\d{1,4}
之前存在。回溯发生在这里。

这是因为您的模式没有考虑两个连续的连字符。由于所有连字符都是可选的,因此会找到第二个匹配项。例如,请参阅链接Casimir。我想我的问题不清楚。为什么正则表达式模式被赋予了
findall()
甚至与0987匹配?哎呀,对不起,Casimir。我的坏朋友,太棒了。谢谢你澄清阿维纳什。快速跟进:
>>re.findall('\d{1,3}[-\s]{1}\d{1,3}[-\s]{1}\d{1,4}',123-345--0987')
返回
[]
。为什么这是空白的?我本以为它至少会因为双破折号而返回
['123-345']
。请尝试
re.findall('\d{1,3}[-\s]{1}\d{1,3}[-\s]{2}\d{1,4}','123-345--0987')
123-345--0987   \d{1,3}[-\s]?\d{1,3}[-\s]?\d{1,4}