貪婪和非貪婪
阿新 • • 發佈:2018-11-08
- 貪婪匹配:當正則表示式中包含能接受到重複的限定符時,通常的行為是匹配儘可能多的字元,這中匹配方式叫做貪婪匹配。特徵是一次性讀入整個字串經行匹配,每當不匹配就捨棄最右邊一個字元,繼續匹配,依次匹配和捨棄,直到匹配成功或者把整個字串捨棄為止,因此它是一種最大化資料返回,能多不會少。
前面我們講過重複限定符,其實這些限定符就是貪婪量詞,比如表示式:\d{3,6}
用來匹配3到6位數字,在這種情況下,它是一種貪婪模式匹配,也就是假如字串裡有6個數字匹配,那它就會全部匹配到。
String test = "61762828 176 2991 871"; String reg= "\\d{3,6}"; Pattern pattern = Pattern.compile(reg); Matcher mc = pattern.matcher(test); while (mc.find()) { System.out.println("匹配結果:" + mc.group()); } // 匹配結果:617628 // 匹配結果:176 // 匹配結果:2991 // 匹配結果:871
由結果可見:本來字串中的“61762828”這一段,其實只需要出現“617”就已經匹配成功了,但它並不滿足,而是匹配到了最大能匹配的字元,也就是6個。
那麼有人會問,如果多個貪婪量詞湊在一起,那他們是如何支配自己的匹配權的呢?
是這樣的,多個貪婪在一起時,如果字串能滿足他們各自最大程度的匹配時,就互不干擾,但如果不能滿足時,會根據深度優先的原則,也就是從左到右的每一個貪婪量詞,優先最大數量的滿足,剩餘再分配下一個量詞匹配。
String test = "61762828 176 2991 87321"; String reg = "(\\d{1,2})(\\d{3,4})"; Pattern pattern = Pattern.compile(reg); Matcher mc = pattern.matcher(test);while (mc.find()) { System.out.println("匹配結果:" + mc.group()); } // 匹配結果:617628 // 匹配結果:2991 // 匹配結果:87321
“617628” 是前面的\d{1,2}匹配出了61,後面的匹配出了7628
"2991" 是前面的\d{1,2}匹配出了29 ,後面的匹配出了91
"87321"是前面的\d{1,2}匹配出了87,後面的匹配出了321
- 懶惰(非貪婪)
懶惰匹配:當正則表示式中包含能接受重複的限定符時,通常的行為是匹配儘可能少的字元,這種匹配方式叫做懶惰匹配。特性:從左到右,從字串的最左邊開始匹配,每次試圖不讀入字元匹配,匹配成功,則完成匹配,否則讀入一個字元再匹配,依次迴圈(讀入字元,匹配)直到匹配成功或者把字串的字元匹配完為止。
程式碼 | 說明 |
*? | 重複任意次,但儘可能少重複 |
+? | 重複1次或更多次,但儘可能少重複 |
?? | 重複0次或1次,但儘可能少重複 |
{n,m}? | 重複n到m次,但儘可能少重複 |
{n,}? | 重複n次以上,但儘可能少重複 |
String reg = "(\\d{1,2}?)(\\d{3,4})"; String test = "61762828 176 2991 87321"; System.out.println("文字:" + test); System.out.println("貪婪模式:" + reg); Pattern p1 = Pattern.compile(reg); Matcher m1 = p1.matcher(test); while (m1.find()) { System.out.println("匹配結果:" + m1.group(0)); } // 文字:61762828 176 2991 87321 // 貪婪模式:(\d{1,2}?)(\d{3,4}) // 匹配結果:61762 // 匹配結果:2991 // 匹配結果:87321
“61762” 是左邊的懶惰匹配出6,右邊的貪婪匹配出1762
"2991" 是左邊的懶惰匹配出2,右邊的貪婪匹配出991
"87321" 左邊的懶惰匹配出8,右邊的貪婪匹配出7321