JAVA 正規表示式的三種模式: 貪婪, 勉強和佔有的討論

xiaoliuliu2050發表於2018-06-21

假設待處理的字串是  xfooxxxxxxfoo

    模式.*foo (貪婪模式): 

模式分為子模式p1(.*)和子模式p2(foo)兩個部分. 其中p1中的量詞匹配方式使用預設方式(貪婪型)。 

匹配開始時,吃入所有字元xfooxxxxxx去匹配子模式p1。匹配成功,但這樣以來就沒有了字串去匹配子模式p2。本輪匹配失敗;第二輪:減少p1部分的匹配量,吐出最後一個字元, 把字串分割成xfooxxxxxxfo和o兩個子字串s1和s2。 s1匹配p1, 但s2不匹配p2。本輪匹配失敗;第三輪,再次減少p1部分匹配量,吐出兩個字元, 字串被分割成xfooxxxxxxfo和oo兩部分。結果同上。第四輪,再次減少p1匹配量, 字串分割成xfooxxxxxx和foo兩個部分, 這次s1/s2分別和p1/p2匹配。停止嘗試,返回匹配成功。


    模式.*?foo (勉強模式): 最小匹配方式。

第一次嘗試匹配, p1由於是0或任意次,因此被忽略,用字串去匹配p2,失敗;第二次,讀入第一個字元x, 嘗試和p1匹配, 匹配成功; 字串剩餘部分fooxxxxxxfoo中前三個字元和p2也是匹配的. 因此, 停止嘗試, 返回匹配成功。在這種模式下,如果對剩餘字串繼續去尋找和模式相匹配的子字串,還會找到字串末尾的另一個xfoo,而在貪婪模式下,由於第一次匹配成功的子串就已經是所有字元,因此不存在第二個匹配子串


    模式.*+foo (侵佔模式): 也叫佔用模式。

匹配開始時讀入所有字串, 和p1匹配成功, 但沒有剩餘字串去和p2匹配。因此, 匹配失敗。返回。

簡單地說, 貪婪模式和佔有模式相比, 貪婪模式會在只有部分匹配成功的條件下, 依次從多到少減少匹配成功部分模式的匹配數量, 將字元留給模式其他部分去匹配; 而佔用模式則是佔有所有能匹配成功部分, 絕不留給其他部分使用。

 

再看下面一個例子:貪婪模式與侵佔模式的比較
正則:\w+[a-z]與\w++[a-z]
目標串:232hjdhfd7474$
分析:①\w+[a-z]:\w+屬於貪婪模式,會一次性吃掉它所能吃掉的所有的字元,也就是子串232hjdhfd7474,此時[a-z]不能夠找到匹配了,故\w+匹配的串會吐出一個字元4,但此時還是得不到匹配。反覆的這樣吐出回退,直到吐出字元d時,此時[a-z]能夠匹配h,所以這時正規表示式會返回一次成功的匹配結果,為232hjdhfd
②\w++[a-z]:\w++屬於侵佔模式,它會一次性吃掉它所能夠吃掉的所有字元,即子串232hjdhfd7474,而且不留給其他部分使用,故不會回退。此時[a-z]不能夠找到匹配,所以此次匹配失敗。在餘下的子串中也找不到能匹配成功的子串。所以整個正規表示式是找不到匹配結果的!

 

量 詞 種 類意  義
貪婪勉強侵佔
X?X??X?+匹配 X 零次或一次
X*X*?X*+匹配 X 零次或多次
X+X+?X++匹配 X 一次或多次
X{n}X{n}?X{n}+匹配 X n 次(這個應該不存在這幾種模式,就是固定匹配n個)
X{n,}X{n,}?X{n,}+匹配 X 至少 n 次
X{n,m}X{n,m}?X{n,m}+匹配 X 至少 n 次,但不多於 m 次

相關文章