| 模式 | 符號 | 匹配策略 | 特點 |
|---|---|---|---|
| 貪婪 | * + ? {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.*bbbPattern p = Pattern.compile(".*bbb");
Matcher m = p.matcher("abbbaabbbaaabbb1234");
while (m.find()) System.out.println(m.group());
// 僅輸出: abbbaabbbaaabbb (匹配最長,吞掉前面所有)
回溯過程:從末尾向前嘗試,最終在最後一個 bbb 停下。
.*?bbbPattern p = Pattern.compile(".*?bbb");
Matcher m = p.matcher("abbbaabbbaaabbb1234");
while (m.find()) System.out.println(m.group());
// 輸出三次:
// abbb
// aabbb
// aaabbb
從開頭向後擴展,最早滿足 bbb 即停止,然後從下一位繼續。
.*+bbbPattern 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() 判斷是否匹配到末尾。理解三種量詞的回溯機制,是寫出高性能、正確正則的關鍵。**貪婪求多、懶惰求少、佔有不悔**——根據業務選擇,性能與正確雙贏。