正規表示式 匹配原理之貪婪與非貪婪

2021-09-28 14:15:01 字數 3786 閱讀 2763

只因貧道學習爬蟲,爬網頁的時候總也得不到想要的結果,故而baidu一番,但是晦澀難懂,便根據自己心得留下只言片語,靜等有緣人

我所理解的貪婪和非貪婪模式,是用於正則中多次匹配元素時的取值方式。

以下使用貪吃蛇的方式說明

1. 貪婪模式

只要能完成正規表示式,能吃多少吃多少,不怕胖

2. 非貪婪模式

只能能完成正規表示式,我能少吃就少吃。**

所以在被量詞修飾的正規表示式中由於這兩種模式的不同就有可能會出現不同的結果。

貪婪模式:

*	匹配上乙個元素零次或多次

+ 匹配上乙個元素一次或多次

? 匹配前面的元素零次或一次  

匹配上乙個元素恰好n次

匹配上乙個元素至少n次

匹配上乙個元素至少n次,但不多於m次

因為本次討論的是貪婪和非貪婪,所以其中確定次數的量詞就沒有談論的必要,『?』和『』不討論

非貪婪模式:(在貪婪限定符後多加乙個?)

*?	匹配上乙個元素零次或多次,但次數盡可能少

+? 匹配上乙個元素一次或多次,但次數盡可能少

? 匹配上乙個元素至少 n 次,但次數盡可能少

? 匹配上乙個元素的次數介於 n 和 m 之間,但次數盡可能少

例子主要以*限定符進行介紹,因*相當於。而+道理是相同的。

我將以下面的p標籤進行演示這兩種模式,根據例子講解原理

第一段文字

第二段文字

第三段文字,注意這裡沒有p的閉合標籤,這是錯誤的html

**(python)

import re

class regextest:

def greedy(self,text):

# 貪婪模式

regix = ''

greedy_pattern = re.compile(regix,re.s)

result = greedy_pattern.findall(text)

print('----------貪婪模式------------')

print(result)

def ungreedy(self,text):

# 非貪婪模式

regix = ''

ungreedy_pattern = re.compile(regix,re.s)

result = ungreedy_pattern.findall(text)

print('-----------非貪婪模式----------')

print(result)

if __name__ == '__main__':

text = ' 第一段文字

第二段文字

第三段文字,注意這裡沒有p的閉合標籤'

regextest().greedy(text)

regextest().ungreedy(text)

列印結果:

----------貪婪模式------------

['第一段文字

第二段文字']

-----------非貪婪模式----------

['第一段文字', '第二段文字']

**中:

正則標識式 貪婪模式:非貪婪模式:

意思是匹配以開頭,以

結尾的字串,但是得到的結果卻是不同的。

其中 re.s引數的意思為全文匹配

結果中:

貪婪模式獲得的列表只有乙個元素,非貪婪模式獲得兩個元素

貪婪模式將

標籤當成元素取了出來

為什麼呢?

首先不論是貪婪還是非貪婪模式,正規表示式在匹配時都是乙個字元乙個字元對比。

貪婪模式原則:能拿多少拿多少

首先正則匹配<text中第乙個<匹配上了(放籃子1),然後匹配正則中的p,但是text中第二個是d,匹配失敗(將籃子1的<扔掉),重新匹配<。進行相同的操作直到找到了第乙個

匹配.*,這個限制符的意思是只要是單字元我都要放籃子2,所以後面的所有字元都被放到了籃子2。

但是發現正規表示式後面還有

沒匹配呢,所以.*開始從籃子2中將text裡的字元乙個乙個拿出來讓最後的

匹配。(順序是先進後出原則)

開始從.*乙個乙個拿出來的text對比,直到匹配上了最後乙個

第一次匹配結束,然後進行下一次匹配,從第一次迴圈的結束位置的下乙個字元開始規則迴圈1-4,發現沒有與 1 匹配的字元,結束整個匹配。

準確的說不應該把

看做乙個整體,實際匹配的原理與 1 類似。暫且看成整體方便理解貪婪模式

結果:只有乙個元素的列表,將中間的

直接取了出來

----------貪婪模式------------

['第一段文字

第二段文字']

非貪婪模式原則:能不拿就不拿

首先正則匹配<text中第乙個<匹配上了(放籃子1),然後匹配正則中的p,但是text中第二個是d,匹配失敗(將籃子1的<扔掉),重新匹配<。進行相同的操作直到找到了第乙個

然後到.*?開始匹配了,因為*的意思是 0個或多個,所以.*?

先匹配,但是

發現與匹配不上,最後讓.*?放進了籃子2

再向下匹配.*?繼續讓

先匹配(迴圈2)····如果

能匹配上就結束本次匹配,進行下次匹配迴圈,如果

匹配不上就放進.*?的籃子2裡,繼續本次迴圈。

結果:得到兩個元素的列表

-----------非貪婪模式----------

['第一段文字', '第二段文字']

兩種模式概括就是:

貪婪模式:我不管後續的規則,符合我要求的字元我都先拿走,直到出現不符合我的要求或者字元拿完停止,如果後續規則不夠了,我再一點一點掏出來。

非貪婪模式:先滿足我最低的要求,後面的字元,不管符不符合我的要求,我都先問問後面的規則,如果符合後面規則就結束我的需求,不再獲取字元。

*?+?是類似,區別在於+?是只要我要先拿到乙個符合我條件的字元,後續字元都用後續的規則匹配。

正規表示式 貪婪與非貪婪匹配

貪婪匹配與非貪婪匹配 貪婪匹配 預設情況下,正規表示式使用最長匹配原則 也叫貪婪匹配原則 例如 要將 zoom 中匹配 zo?的部 分替換成 r 替換的的結果是 rom 如果要將 zoom 中匹配 zo 的部分替換成 r 替換後的結果是 rm 非貪婪匹配 當字元?緊隨其他限定符 之後時,匹配模式變成...

正規表示式 貪婪與非貪婪匹配

貪婪匹配與非貪婪匹配 貪婪匹配 預設情況下,正規表示式使用最長匹配原則 也叫貪婪匹配原則 例如 要將 zoom 中匹配 zo?的部 分替換成 r 替換的的結果是 rom 如果要將 zoom 中匹配 zo 的部分替換成 r 替換後的結果是 rm 非貪婪匹配 當字元?緊隨其他限定符 之後時,匹配模式變成...

正規表示式 貪婪與非貪婪匹配

貪婪匹配與非貪婪匹配 貪婪匹配 預設情況下,正規表示式使用最長匹配原則 也叫貪婪匹配原則 例如 要將 zoom 中匹配 zo?的部 分替換成 r 替換的的結果是 rom 如果要將 zoom 中匹配 zo 的部分替換成 r 替換後的結果是 rm 非貪婪匹配 當字元?緊隨其他限定符 之後時,匹配模式變成...