import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Test {
public static void main(String[] args) {
String str = "<biao><>c<b>";
Pattern pattern;
Matcher matcher;
// 貪婪: 最長(zhǎng)匹配 .* : 輸出: <biao><>c<b>
pattern = Pattern.compile("<.*>");
matcher = pattern.matcher(str);
while (matcher.find()) {
System.out.println(matcher.group());
}
// 不知是否非貪婪 .*? : 輸出: <biao>, <>, <b>
pattern = Pattern.compile("<.*?>");
matcher = pattern.matcher(str);
while (matcher.find()) {
System.out.println(matcher.group());
}
// 使用組, 輸出<>里的內(nèi)容, 輸出: 'biao', ' ', 'b'
// 0組代表整個(gè)表達(dá)式, 子組從1開(kāi)始
pattern = Pattern.compile("<(.*?)>");
matcher = pattern.matcher(str);
while (matcher.find()) {
System.out.println(matcher.group(1));
}
}
}
貪婪、勉強(qiáng)和侵占量詞間的不同
在貪婪、勉強(qiáng)和侵占三個(gè)量詞間有著細(xì)微的不同。
貪婪(*, ?, +):讀入整個(gè)串,從后往前匹配
勉強(qiáng)(*?, ??, +?):從前往后匹配
侵占(*+, ?+, ++):讀入整個(gè)串,從前往后匹配,匹配的是整個(gè)串
貪婪量詞之所以稱之為“貪婪的”,這是由于它們強(qiáng)迫匹配器讀入(或者稱之為吃掉)整個(gè)輸入的字符串,來(lái)優(yōu)先嘗試第一次匹配,如果第一次嘗試匹配(對(duì)于整個(gè)輸入的字符串)失敗,匹配器會(huì)通過(guò)回退整個(gè)字符串的一個(gè)字符再一次進(jìn)行嘗試,不斷地進(jìn)行處理直到找到一個(gè)匹配,或者左邊沒(méi)有更多的字符來(lái)用于回退了。賴于在表達(dá)式中使用的量詞,最終它將嘗試地靠著 1 或 0 個(gè)字符的匹配。
但是,勉強(qiáng)量詞采用相反的途徑:從輸入字符串的開(kāi)始處開(kāi)始,因此每次勉強(qiáng)地吞噬一個(gè)字符來(lái)尋找匹配,最終它們會(huì)嘗試整個(gè)輸入的字符串。
最后,侵占量詞始終是吞掉整個(gè)輸入的字符串,嘗試著一次(僅有一次)匹配。不像貪婪量詞那樣,侵占量詞絕不會(huì)回退,即使這樣做是允許全部的匹配成功。
為了說(shuō)明一下,看看輸入的字符串是 xfooxxxxxxfoo 時(shí)。
Enter your regex: .*foo // 貪婪量詞
Enter input string to search: xfooxxxxxxfoo
I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13.
Enter your regex: .*?foo // 勉強(qiáng)量詞
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 // 侵占量詞
Enter input string to search: xfooxxxxxxfoo
No match found.
第一個(gè)例子使用貪婪量詞.*,尋找緊跟著字母“f”“o”“o”的“任何東西”零次或者多次。由于量詞是貪婪的,表達(dá)式的.*部分第一次“吃掉”整個(gè)輸入的字符串。在這一點(diǎn),全部表達(dá)式不能成功地進(jìn)行匹配,這是由于最后三個(gè)字母(“f”“o”“o”)已經(jīng)被消耗掉了。那么匹配器會(huì)慢慢地每次回退一個(gè)字母,直到返還的“foo”在最右邊出現(xiàn),這時(shí)匹配成功并且搜索終止。
然而,第二個(gè)例子采用勉強(qiáng)量詞,因此通過(guò)首次消耗“什么也沒(méi)有”作為開(kāi)始。由于“foo”并沒(méi)有出現(xiàn)在字符串的開(kāi)始,它被強(qiáng)迫吞掉第一個(gè)字母(“x”),在 0 和 4 處觸發(fā)了第一個(gè)匹配。測(cè)試用具會(huì)繼續(xù)處理,直到輸入的字符串耗盡為止。在 4 和 13 找到了另外一個(gè)匹配。
第三個(gè)例子的量詞是侵占,所以在尋找匹配時(shí)失敗了。在這種情況下,整個(gè)輸入的字符串被.*+消耗了,什么都沒(méi)有剩下來(lái)滿足表達(dá)式末尾的“foo”。
你可以在想抓取所有的東西,且決不回退的情況下使用侵占量詞,在這種匹配不是立即被發(fā)現(xiàn)的情況下,它將會(huì)優(yōu)于等價(jià)的貪婪量詞。