天天看点

Python正则运算符优先级re.findall('(.)*',

我们分别执行三个语句:

>>> re.findall('(.)*',"abc")         
['c', '']
>>> re.findall('(.*)',"abc")
['abc', '']
>>> re.findall('(.?)*',"abc")        
['', '']
>>>
      

可以看到三个执行结果完全不同,为什么会这样呢?老猿才开始没弄明白。我们使用《​​妙用re.sub分析正则表达式解析匹配过程​​》介绍的方法parsematch来分析一下这三个匹配语句:

>>> parsematch('(.)*',"abc")           
第1次匹配,匹配情况:
    匹配子串group(0): abc,位置为:(0, 3)
    匹配子串group(1): c,位置为:(2, 3)
第2次匹配,m.lastindex=None,匹配情况:
    匹配子串group(0): ,位置为:(3, 3)

可以看到“(.)*”是每次匹配一个字母,再重复匹配过程直到匹配不到字母前停止,所以最后匹配结果是字符“c”,在“c”之后是空字符串,由于*的原因也会匹配成功。

>>> parsematch('(.*)',"abc")           
第1次匹配,匹配情况:
    匹配子串group(0): abc,位置为:(0, 3)
    匹配子串group(1): abc,位置为:(0, 3)
第2次匹配,匹配情况:
    匹配子串group(0): ,位置为:(3, 3)
    匹配子串group(1): ,位置为:(3, 3)

      

可以看到“(.*)”是第一次匹配是匹配所有字符"abc",匹配到搜索文本结束,第二次匹配空字符串也是匹配成功。

>>> parsematch('(.?)*',"abc")          
第1次匹配,匹配情况:
    匹配子串group(0): abc,位置为:(0, 3)
    匹配子串group(1): ,位置为:(3, 3)
第2次匹配,匹配情况:
    匹配子串group(0): ,位置为:(3, 3)
    匹配子串group(1): ,位置为:(3, 3)
>>>
      

可以看到“(.?)*”是每次匹配0-1个字符,再执行星号指定的重复匹配过程直到匹配到“c”之后,由于“abc”[3:3]也能匹配成功,因此最后匹配结果是空串。

第2次匹配“c”之后的空串开始,也是匹配成功,因此又会匹配到空串。

  1. 关于正则表达式优先级请参考《​​第11.26 Python正则表达式运算符优先级​​》;
  2. 正则表达式解析匹配过程请参考《​​妙用re.sub分析正则表达式解析匹配过程​​》;
  3. 贪婪模式和非贪婪模式的匹配处理过程请参考《​​Python正则表达式W+和W*匹配过程的深入分析​​》的相关分析。