正則表達式之貪婪匹配與非貪婪匹配

在前面正則表達式匹配規則裏,提到了 .*

. :匹配除 "\n" 之外的任何單個字符。要匹配包括 '\n' 在內的任何字符,請使用像 '[.\n]' 的模式

* :匹配0個或多個

使用 .* 的話就可以匹配任意長度的任意字符,但是有時候在使用 .*時就可能匹配不到物品們想要的結果,例:

import re

s='hello 1234567 world'
res = re.match('he.*(\d).*rld$',s)

print(res.group(1))

這裏要獲取中間的數字,正則表達式這樣寫看似沒什麼問題,但是運行結果卻只有 7 這是怎麼回事呢?

這裏就涉及一個貪婪匹配與非 貪婪匹配的問題了。在貪婪匹配下,.* 會匹配儘可能多的字符。正則表達式中.*後面是\d+,也就是至少一個數字,並沒有指定具體多少個數字,因此,.*就儘可能匹配多的字符,這裏就把123456匹配了,給\d+留下個可滿 足條件的數字 7.最後得到的內容就只有數字7了。

           但這很明顯會給我們帶來很大的不便。有時候,匹配結果會莫名其妙少了部分內容。 其實,這裏只需要使用非貪婪匹配就好了。非貪婪匹配的寫法是.*?,多了一個?,那麼它可以達到怎樣的效果?我們再用實例看一下:

import re

s='hello 1234567 world'
res = re.match('he.*?(\d).*rld$',s)

print(res.group(1))

這裏我們只是將第一個.*改成了.*?. 轉變爲非貪婪匹配。結果如下:

           1234567

           此時就可以成功獲取1234567了。原因可想而知,貪婪匹配是儘可能匹配多的字符,非貪婪匹配就是盡叮能匹配少的字符。當.*?匹配到hello後面的空白字符時,再往後的字符就是數字了,而\d+恰好可以匹配,那麼這裏. *?就不再進行匹配,交給\d+去匹配後面的數字。所以這樣,*?匹配了儘可能少的字符,\d+ 的結果就是1234567了。

            但是這裏需要注意,如果匹配的結果在字符結尾,.*?就有可能匹配不到任何結果了,因爲他會儘可能匹配少的字符,例:

import re

s='hello 1234567 world/python'
res1 = re.match('he.*?(\d).*rld/(.*?)$',s)
res2 = re.match('he.*?(\d).*rld/(.*)$',s)

print('res1',res1.group(2))
print('res2',res2.group(2))

 

運行結果爲:

res1

res2 python

可以觀察到,.*?沒有匹配到任何結果,而.*則儘可能匹配多的字符,成功得到了匹配結果。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章