java正規表示式Greedy、Reluctant、Possessive的深入理解

sayWhat_sayHello發表於2018-07-19

Greedy:貪婪的。一次讀取所有字元進行匹配。再進行回溯。
Reluctant:不情願的。從左往右讀,直到讀完字元序列。
Possessive:獨佔的。一次讀取所有字元進行匹配。不進行回溯。

以下用案例來幫助理解:

Enter your regex: .*foo  // greedy quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13.

Enter your regex: .*?foo  // reluctant quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfoo" starting at index 0 and ending at index 4.
I found the text "xxxxxxfoo" starting at index 4 and ending at index 13.

Enter your regex: .*+foo // possessive quantifier
Enter input string to search: xfooxxxxxxfoo
No match found.

解析:
第一個,貪心型:
.* 貪心就是全都要,直接匹配到了行末,這時候還有foo 還沒匹配,開始從右回溯一個字元o ,匹配了,繼續回溯,又回溯了一個o ,匹配了,繼續回溯,又回溯了一個f ,匹配了。好,結束。

第二個,懶惰型:
.* 懶惰,不情願就是不要,不要沒問題,但是一定要讀完字元序列。所以被迫的讀了一個x,不匹配,繼續讀。f-o-o 匹配了,ok,匹配了一個xfoo ,但是沒找到結尾,只能繼續,然後讀完xxxxxxfoo, 又匹配了,結束。

第三個,獨佔型(os:無比貪心型):
這個理解不難。.*先是貪心就是全都要,直接匹配到了行末,不回溯。好,結束,不匹配。


我們再來看一個案例,這個案例除了匹配還進行了替換,就是將每一個完整的匹配都進行了替換:

Greedy:

    "abbbbc".replaceAll("b+b", "x"); // axc  

Reluctant

    "abbbbc".replaceAll("b+?b", "x"); // axxc  

Possessive

    "abbbbc".replaceAll("b++b", "x"); // abbbbc  

+代表一次或者多次匹配
第一種(貪心型)(b+b;我們這裡把+後面那個b叫成後面的b):
b+貪心,多次匹配b,把所有b匹配完了,即bbbb。加上後面的b發現不符合匹配,開始回溯,從右回溯一個b後加上後面的b,匹配了,ok,結束。

第二種(懶惰型):
b+不貪心,只匹配一次,即b加上後面的b=bb,繼續往後讀又匹配一個bb,匹配完了,結束。

第三種(獨佔型):
b+貪心,多次匹配b,把所有b匹配完了,即bbbb。加上後面的b發現不符合匹配。不回溯,結束。

相關文章