正規表示式通常用於在文字中查詢匹配的字串。正規表示式模式中使用到通配字,當它在從左到右的順序求值時,會盡量「抓取」滿足匹配最長字串。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...