正規表示式中的貪婪模式與非貪婪模式詳解

2022-07-20 05:18:13 字數 2803 閱讀 5644

1 概述 

貪婪與非貪婪模式影響的是被量詞修飾的子表示式的匹配行為,貪婪模式在整個表示式匹配成功的前提下,盡可能多的匹配,而非貪婪模式在整個表示式匹配成功的前提下,盡可能少的匹配。非貪婪模式只被部分nfa引擎所支援。 

屬於貪婪模式的量詞,也叫做匹配優先量詞,包括: 

「」、「」、「?」、「*」和「+」。 

在一些使用nfa引擎的語言中,在匹配優先量詞後加上「?」,即變成屬於非貪婪模式的量詞,也叫做忽略優先量詞,包括: 

「?」、「?」、「??」、「*?」和「+?」。 

從正則語法的角度來講,被匹配優先量詞修飾的子表示式使用的就是貪婪模式,如「(expression)+」;被忽略優先量詞修飾的子表示式使用的就是非貪婪模式,如「(expression)+?」。 

對於貪婪模式,各種文件的叫法基本一致,但是對於非貪婪模式,有的叫懶惰模式或惰性模式,有的叫勉強模式,其實叫什麼無所謂,只要掌握原理和用法,能夠運用自如也就是了。個人習慣使用貪婪與非貪婪的叫法,所以文中都會使用這種叫法進行介紹。 

2 貪婪與非貪婪模式匹配原理

對於貪婪與非貪婪模式,可以從應用和原理兩個角度進行理解,但如果想真正掌握,還是要從匹配原理來理解的。 

先從應用的角度,回答一下「什麼是貪婪與非貪婪模式?」 

2.1 從應用角度分析貪婪與非貪婪模式 

2.1.1 什麼是貪婪與非貪婪模式 

先看乙個例子 

舉例: 

源字串:aatest1

bbtest2

cc 正規表示式一:.*

匹配結果一:test1

bbtest2

正規表示式二:.*?

匹配結果二:test1

(這裡指的是一次匹配結果,所以沒包括test2

) 根據上面的例子,從匹配行為上分析一下,什是貪婪與非貪婪模式。 

正規表示式一採用的是貪婪模式,在匹配到第乙個「

」時已經可以使整個表示式匹配成功,但是由於採用的是貪婪模式,所以仍然要向右嘗試匹配,檢視是否還有更長的可以成功匹配的子串,匹配到第二個「

」後,向右再沒有可以成功匹配的子串,匹配結束,匹配結果為「test1

bbtest2

」。當然,實際的匹配過程並不是這樣的,後面的匹配原理會詳細介紹。 

僅從應用角度分析,可以這樣認為,貪婪模式,就是在整個表示式匹配成功的前提下,盡可能多的匹配,也就是所謂的「貪婪」,通俗點講,就是看到想要的,有多少就撿多少,除非再也沒有想要的了。 

正規表示式二採用的是非貪婪模式,在匹配到第乙個「

」時使整個表示式匹配成功,由於採用的是非貪婪模式,所以結束匹配,不再向右嘗試,匹配結果為「test1

」。 僅從應用角度分析,可以這樣認為,非貪婪模式,就是在整個表示式匹配成功的前提下,盡可能少的匹配,也就是所謂的「非貪婪」,通俗點講,就是找到乙個想要的撿起來就行了,至於還有沒有沒撿的就不管了。

2.1.2 關於前提條件的說明 

在上面從應用角度分析貪婪與非貪婪模式時,一直提到的乙個前提條件就是「整個表示式匹配成功」,為什麼要強調這個前提,我們看下下面的例子。 

正規表示式三:.*

bb 匹配結果三:test1

bb 修飾「.」的仍然是匹配優先量詞「*」,所以這裡還是貪婪模式,前面的「.*

」仍然可以匹配到「test1

bbtest2

」,但是由於後面的「bb」無法匹配成功,這時「.*

」必須讓出已匹配的「bbtest2

」,以使整個表示式匹配成功。這時整個表示式匹配的結果為「test1

bb」,「.*

」匹配的內容為「test1

」。可以看到,在「整個表示式匹配成功」的前提下,貪婪模式才真正的影響著子表示式的匹配行為,如果整個表示式匹配失敗,貪婪模式只會影響匹配過程,對匹配結果的影響無從談起。 

非貪婪模式也存在同樣的問題,來看下面的例子。 

正規表示式四:.*?

cc 匹配結果四:test1

bbtest2

cc 這裡採用的是非貪婪模式,前面的「.*?

」仍然是匹配到「test1

」為止,此時後面的「cc」無法匹配成功,要求「.*?

」必須繼續向右嘗試匹配,直到匹配內容為「test1

bbtest2

」時,後面的「cc」才能匹配成功,整個表示式匹配成功,匹配的內容為「test1

bbtest2

cc」,其中「.*?

」匹配的內容為「test1

bbtest2

」。可以看到,在「整個表示式匹配成功」的前提下,非貪婪模式才真正的影響著子表示式的匹配行為,如果整個表示式匹配失敗,非貪婪模式無法影響子表示式的匹配行為。 

2.1.3 貪婪還是非貪婪——應用的抉擇 

通過應用角度的分析,已基本了解了貪婪與非貪婪模式的特性,那麼在實際應用中,究竟是選擇貪婪模式,還是非貪婪模式呢,這要根據需求來確定。 

對於一些簡單的需求,比如源字元為「aatest1

bb」,那麼取得div標籤,使用貪婪與非貪婪模式都可以取得想要的結果,使用哪一種或許關係不大。 

但是就2.1.1中的例子來說,實際應用中,一般一次只需要取得乙個配對出現的div標籤,也就是非貪婪模式匹配到的內容,貪婪模式所匹配到的內容通常並不是我們所需要的。 

那為什麼還要有貪婪模式的存在呢,從應用角度很難給出滿意的解答了,這就需要從匹配原理的角度去分析貪婪與非貪婪模式。 

2.2 從匹配原理角度分析貪婪與非貪婪模式 

如果想真正了解什麼是貪婪模式,什麼是非貪婪模式,分別在什麼情況下使用,各自的效率如何,那就不能僅僅從應用角度分析,而要充分了解貪婪與非貪婪模式的匹配原理。 

文章**自

正規表示式貪婪與非貪婪模式

之前做程式的時候看到過正規表示式的貪婪與非貪婪模式,今天用的時候就想不起來了,現在這裡總結一下,以備自己以後用到注意。1.什麼是正規表示式的貪婪與非貪婪匹配 如 string str abcaxc patter p ab c 貪婪匹配 正規表示式一般趨向於最大長度匹配,也就是所謂的貪婪匹配。如上面使...

正規表示式貪婪與非貪婪模式

1.什麼是正規表示式的貪婪與非貪婪匹配 如 string str abcaxc patter p ab c 貪婪匹配 正規表示式一般趨向於最大長度匹配,也就是所謂的貪婪匹配。如上面使用模式p匹配字串str,結果就是匹配到 abcaxc ab c 非貪婪匹配 就是匹配到結果就好,就少的匹配字元。如上面...

正規表示式 貪婪非貪婪模式

貪婪與非貪婪模式影響的是被量詞修飾的子表示式的匹配行為,貪婪模式在整個表示式匹配成功的前提下,盡可能多的匹配,而非貪婪模式在整個表示式匹配成功的前提下,盡可能少的匹配。非貪婪模式只被部分nfa引擎所支援。1.舉乙個例子 string str abcaxc patter p ab.c 貪婪匹配 正規表...