首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 正則表達式:貪婪、懶惰、佔有優先量詞深度解析

     編輯:Java 相關知識

三種量詞模式對比

模式符號匹配策略特點
貪婪* + ? {n,m}先嘗試匹配**最長**子串,失敗則逐步回溯減少默認模式,匹配盡可能多
懶惰 (非貪婪)*? +? ?? {n,m}?先嘗試匹配**最短**子串,失敗則逐步擴展增加匹配盡可能少,加 ? 後綴
佔有優先*+ ++ ?+ {n,m}+**只嘗試匹配整個串**,失敗直接放棄,**不回溯**性能最好,防止災難性回溯,Java 支持,JS 不支持

量詞對照表

貪婪    懶惰      佔有優先    說明
?       ??        ?+         0 或 1 次
*       *?        *+         0 次或多次
+       +?        ++         1 次或多次
{n}     {n}?      {n}+       精確 n 次
{n,m}   {n,m}?    {n,m}+     n 到 m 次
{n,}    {n,}?     {n,}+      至少 n 次

實戰演示:字符串 abbbaabbbaaabbb1234 提取 abbb/aabbb/aaabbb

貪婪 .*bbb

Pattern p = Pattern.compile(".*bbb");
Matcher m = p.matcher("abbbaabbbaaabbb1234");
while (m.find()) System.out.println(m.group());
// 僅輸出: abbbaabbbaaabbb (匹配最長,吞掉前面所有)

回溯過程:從末尾向前嘗試,最終在最後一個 bbb 停下。

懶惰 .*?bbb

Pattern p = Pattern.compile(".*?bbb");
Matcher m = p.matcher("abbbaabbbaaabbb1234");
while (m.find()) System.out.println(m.group());
// 輸出三次:
// abbb
// aabbb
// aaabbb

從開頭向後擴展,最早滿足 bbb 即停止,然後從下一位繼續。

佔有優先 .*+bbb

Pattern p = Pattern.compile(".*+bbb"); // Java 支持
Matcher m = p.matcher("abbbaabbbaaabbb1234");
System.out.println(m.find()); // false
// .*+ 直接吞掉整個串,留給 bbb 的字符已無,匹配失敗,不回溯

性能與災難性回溯

貪婪量詞在複雜模式 (如 (a+)+b 匹配 aaaaaaaaac) 會導致指數級回溯,CPU 飆升。**佔有優先量詞 (++, *+) 完全禁用回溯,是防禦 ReDoS (正則拒絕服務) 的利器**。

最佳實踐建議

  • **默認用懶惰** (*?, +?) 當你只想匹配「直到某個標記」時 (如 HTML 標簽 <.*?>)。
  • **確定結構時用佔有優先** (++, *+) 避免回溯開銷 (如 \\d++ 匹配純數字)。
  • **避免嵌套量詞** ((a*)*),極易導致災難性回溯。
  • 使用 Pattern.compile(regex, Pattern.COMMENTS) 寫可讀正則,利用 Matcher.hitEnd() 判斷是否匹配到末尾。

總結

理解三種量詞的回溯機制,是寫出高性能、正確正則的關鍵。**貪婪求多、懶惰求少、佔有不悔**——根據業務選擇,性能與正確雙贏。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved