正則表示式——貪婪非貪婪模式
貪婪與非貪婪模式影響的是被量詞修飾的子表示式的匹配行為,貪婪模式在整個表示式匹配成功的前提下,儘可能多的匹配,而非貪婪模式在整個表示式匹配成功的前提下,儘可能少的匹配。非貪婪模式只被部分NFA引擎所支援。
1.舉一個例子:
String str="abcaxc";
Patter p="ab.*c";
貪婪匹配:正則表示式一般趨向於最大長度匹配,也就是所謂的貪婪匹配。如上面使用模式p匹配字串str,結果就是匹配到:abcaxc。
非貪婪匹配:就是匹配到結果就好,就少的匹配字元。如上面使用模式p匹配字串str,結果就是匹配到:abc。
2.程式設計中如何區分兩種模式
預設是貪婪模式;在量詞後面直接加上一個問號?就是非貪婪模式。
量詞:
{m,n}:m到n個
*:任意多個
+:一個到多個
?:0或一個
3.原理:
結合例項來分析哈基於正則的引擎對文字的匹配過程。原始字串:This is a <EM>first</EM> test,使用正則<.+>來匹配HTML標籤,期望第一次匹配得到<EM>,第二次匹配得到</EM>,實際卻是第一次匹配就得到了<EM>first</EM>。
來看看匹配過程,第一個記號是<,這是一個文字字元,匹配其自身。第二個符號是.,匹配了字元E,然後+一直可以匹配其餘的字元,直到一行的結束。然後到了換行符,匹配失敗(.不匹配換行符)。於是引擎開始對下一個正則表示式符號進行匹配,即試圖匹配>。到目前為止,<.+已經匹配了<EM>first</EM> test。引擎會試圖將>與換行符進行匹配,結果失敗了。於是引擎進行回溯。回溯後的匹配狀況是 <.+ 匹配 <EM>first</EM> tes。於是引擎將>與t進行匹配。顯然還是會失敗。這個過程繼續,直到 <.+ 匹配 <EM>first</EM,>與>匹配。於是引擎找到了一個匹配<EM>first</EM>。記住,正則導向的引擎是急切的,所以它會急著報告它找到的第一個匹配。而不是繼續回溯,即使可能會有更好的匹配,例如<EM>。所以我們可以看到,由於+的貪婪性,使得正則表示式引擎返回了一個最左邊的最長的匹配。
如果想得到期望的結果,就需要啟用非貪婪模式:<.+?>
總結:如果是貪婪匹配模式,正則引擎會一直匹配到字串最後;當匹配為false時,就回溯以找到倒數第一個匹配位置,返回匹配結果。 如果是非貪婪匹配模式,正則引擎會匹配到符合pattern的末尾位置那個字元,然後再往後走一步,發現匹配為false時,就回溯以找到最近一個匹配為true的位置,返回匹配結果。