python re模組匹配時貪婪和非貪婪模式

2021-08-16 05:58:10 字數 3902 閱讀 9005

正規表示式通常用於在文字中查詢匹配的字串。正規表示式模式中使用到通配字,當它在從左到右的順序求值時,會盡量「抓取」滿足匹配最長字串。python裡數量詞預設是貪婪的(在少數語言裡也可能是預設非貪婪),總是嘗試匹配盡可能多的字元;非貪婪則相反,總是嘗試匹配盡可能少的字元。在"*","?","+",""後面加上?,使貪婪變成非貪婪

預設情況下,正規表示式將進行貪婪匹配。所謂「貪婪」,其實就是在多種長度的匹配字串中,選擇較長的那乙個。例如,如下正規表示式本意是選出人物所說的話,但是卻由於「貪婪」特性,出現了匹配不當:

>>> sentence = """you said "why?" and i say "i don't know"."""

>>> re.findall(r'"(.*)"', sentence)

['why?" and i say "i don\'t know']

當我們期望正規表示式「非貪婪」地進行匹配時,需要通過語法明確說明: 

?捕獲2-5次,但是優先次數少的匹配

在這裡,問號?可能會有些讓人犯暈,因為之前他已經有了自己的含義:前面的匹配出現0次或1次。其實,只要記住,當問號出現在表現不定次數的正規表示式部分之後時,就表示非貪婪匹配。 

非貪婪例子:

>>> sentence = """you said "why?" and i say "i don't know"."""

>>> re.findall(r'"(.*?)"', sentence)

['why?', "i don't know"]

>>> re.findall('hi*?', 'hiiiii')

['h']

>>> re.findall('hi?', 'hiiiii')

['hii']

>>> re.findall('hi?', 'hiiiii')

['hi']

例子:

import re

content = 'hello 1234567 world_this is a demo'

result = re.match('^he.*(\d+).*demo$', content)

print(result)

print(result.group(1))

執行結果:

<_sre.sre_match object; span=(0, 35), match='hello 1234567 world_this is a regex demo'>

7

貪婪匹配下,.*會匹配盡可能多的字元,我們的正規表示式中.*後面是\d+,也就是至少乙個數字,並沒有指定具體多少個數字,所以.*就盡可能匹配多的字元,所以它把123456也匹配了,給\d+留下乙個可滿足條件的數字7,所以\d+得到的內容就只有數字7了。

import re

content = 'hello 1234567 world_this is a demo'

result = re.match('^he.*?(\d+).*demo$', content)

print(result)

print(result.group(1))

執行結果:

<_sre.sre_match object; span=(0, 40), match='hello 1234567 world_this is a regex demo'>

1234567

貪婪匹配是盡可能匹配多的字元.*?之後是\d+用來匹配數字,當.*?匹配到hello後面的空白字元的時候,再往後的字元就是數字了,而\d+恰好可以匹配,那麼這裡.*?就不再進行匹配,交給\d+去匹配後面的數字。所以這樣,.*?匹配了盡可能少的字元,\d+的結果就是1234567

>>> re.match(r"aa(\d+)","aa2343ddd").group(1)

'2343'

>>> re.match(r"aa(\d+?)","aa2343ddd").group(1)

'2'>>> re.match(r"aa(\d+)ddd","aa2343ddd").group(1)

'2343'

>>> re.match(r"aa(\d+?)ddd","aa2343ddd").group(1)

'2343'

嚴格來說,這一部分並不是非貪婪特性。但是由於其行為與非貪婪類似,所以為了方便記憶,就將其放在一起了。 

(?=abc)捕獲,但不消耗字元,且匹配abc

(?!abc)捕獲,不消耗,且不匹配abc

在正規表示式匹配的過程中,其實存在「消耗字元」的過程,也就是說,一旦乙個字元在匹配過程中被檢索(消耗)過,後面的匹配就不會再檢索這一字元了。 

例子:想找出字串中出現過1次以上的單詞

>>> sentence = "oh what a day, what a lovely day!"

>>> re.findall(r'\b(\w+)\b.*\b\1\b', sentence)

['what']

在第乙個(\w+)匹配到what,並且其後的\1也匹配到第二個what的時候,「oh what a day, what」這一段子串都已經被正規表示式消耗了,所以之後的匹配,將直接從第二個what之後開始。自然地,這裡只能找出乙個出現了兩次的單詞。 

那麼解決方案,就和上面提到的(?=abc)語法相關了。這樣的語法可以在分組匹配的同時,不消耗字串!所以,正確的書寫方式應該是:

>>> re.findall(r'\b(\w+)\b(?=.*\b\1\b)', sentence)

['what', 'a', 'day']

如果我們需要匹配乙個至少包含兩個不同字母的單詞,則可以使用(?!abc)的語法:

>>> re.search(r'([a-z]).*(?!\1)[a-z]', 'aa', re.ignorecase)

>>> re.search(r'([a-z]).*(?!\1)[a-z]', 'ab', re.ignorecase)

<_sre.sre_match object; span=(0, 2), match='ab'>

則可以匹配字串abba 第乙個圓括號內的正則匹配字元a,則在字串最後\1這個位置必須是字元a,第二個括號匹配字元b,在倒數第二個位置\2必須是字元b 如果有巢狀的圓括號,順序是按左括號的次序計算的

二、\b

\b 稱為單詞邊界(word boundary)符,例如只想匹配 my cat is bad.中的cat 可以使用 \bcat\b

#re.i要在compile的時候指定,注意\b在python中是回退符,正則模式之前一定要加r(raw string)

p = re.compile(

r'\bcat\b'

, re.i)

三、python字串前面加u,r,b的含義

python re模組匹配貪婪和非貪婪模式詳解

python貪婪和非貪婪 正規表示式通常用於在文字程式設計客棧中查詢proouv匹配的字串。python裡數量詞預設是貪婪的 在少數語言裡也可能是預設非貪婪 總是嘗試匹配盡可能多的字元 非貪婪則相反,總是嘗試匹配盡可能少的字元。在 後面加上?使貪婪變成非貪婪。s this is a number 2...

python基礎 re模組匹配時貪婪和非貪婪模式

python貪婪和非貪婪 正規表示式通常用於在文字中查詢匹配的字串。python裡數量詞預設是貪婪的 在少數語言裡也可能是預設非貪婪 總是嘗試匹配盡可能多的字元 非貪婪則相反,總是嘗試匹配盡可能少的字元。在 後面加上?使貪婪變成非貪婪。s this is a number 234 235 22 42...

貪婪匹配和非貪婪匹配

貪婪模式 在整個表示式匹配成功的前提下,盡可能多的匹配 非貪婪模式 在整個表示式匹配成功的前提下,盡可能少的匹配 重複匹配0次或1次 重複匹配0次或更多次 重複匹配1次或更多次 預設情況下是貪婪的!content abbbbc pattern re.compile r ab result patte...