之前已經簡單介紹了Python正則表達式的基礎與捕獲,那么在這一篇文章里,我將總結一下正則表達式的貪婪/非貪婪特性。
貪婪
默認情況下,正則表達式將進行貪婪匹配。所謂“貪婪”,其實就是在多種長度的匹配字符串中,選擇較長的那一個。例如,如下正則表達式本意是選出人物所說的話,但是卻由于“貪婪”特性,出現了匹配不當:
>>> sentence = """You said "why?" and I say "I don't know".""">>> re.findall(r'"(.*)"', sentence)['why?" and I say "I don/'t know']
再比如,如下的幾個例子都說明了正則表達式“貪婪”的特性:
>>> re.findall('hi*', 'hiiiii')['hiiiii']>>> re.findall('hi{2,}', 'hiiiii')['hiiiii']>>> re.findall('hi{1,3}', 'hiiiii')['hiii']
非貪婪
當我們期望正則表達式“非貪婪”地進行匹配時,需要通過語法明確說明:
{2,5}?
捕獲2-5次,但是優先次數少的匹配
在這里,問號?可能會有些讓人犯暈,因為之前他已經有了自己的含義:前面的匹配出現0次或1次。其實,只要記住,當問號出現在表現不定次數的正則表達式部分之后時,就表示非貪婪匹配。
還是上面的那幾個例子,用非貪婪匹配,則結果如下:
>>> re.findall('hi*?', 'hiiiii')['h']>>> re.findall('hi{2,}?', 'hiiiii')['hii']>>> re.findall('hi{1,3}?', 'hiiiii')['hi']
另外一個例子中,使用非貪婪匹配,結果如下:
>>> sentence = """You said "why?" and I say "I don't know".""">>> re.findall(r'"(.*?)"', sentence)['why?', "I don't know"]
捕獲與非貪婪
嚴格來說,這一部分并不是非貪婪特性。但是由于其行為與非貪婪類似,所以為了方便記憶,就將其放在一起了。
(?=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之后開始。自然地,這里只能找出一個出現了兩次的單詞。
新聞熱點
疑難解答