无法理解RE.findall()在这里做了什么

时间:2015-02-02 15:01:18

标签: 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}[-\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']

我原本以为findall()调用与0987不匹配?我错过了什么?

1 个答案:

答案 0 :(得分:0)

>>>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" matched by \d{1,3}"8" matched by \d{1,3}"7" matched by \d{1,4}

123-345--0987   \d{1,3}

首先\d{1,3}尝试贪婪地匹配所有三位数字。如果没有找到三位数,则它会尝试匹配2位数字,然后匹配一位数字。由于上面的模式是贪婪的,它匹配123345098

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

然后它尝试匹配以下可选的-或空格。因此,123-345-098已匹配。

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

匹配的123-3450987与第二个7匹配,因为您定义的\d{1,3}匹配数字范围从1到3(回溯发生这里)。

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

[-\s]?匹配可选的空格字符或短划线。现在匹配123-345-0987仍然保持不变。因为这种模式是可选的。

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

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