前言
正則表達式是文本處理的瑞士軍刀。本文系統整理 Java 正則核心語法、常用預定義字符類、量詞、分組與斷言,附帶實戰模式速查表,適合開發時快速查閱。
一、 邊界匹配模式
| 模式 | 含義 | 示例 |
^pattern$ | 整個字符串完全匹配 | "123".matches("^\\d+$") → true |
pattern | 部分匹配(子串包含) | "abc123".matches("\\d+") → false,但 find() 可匹配 |
建議:String.matches() 默認全字符串匹配,等同於 ^...$;Matcher.find() 用於部分匹配。
二、 核心元字符與預定義字符類
| 符號 | 說明 | 等價形式 |
\d | 任意數字 | [0-9] |
\D | 任意非數字 | [^0-9] |
\w | 單詞字符(字母、數字、下劃線) | [a-zA-Z0-9_] |
\W | 非單詞字符 | [^a-zA-Z0-9_] |
\s | 空白字符(空格、\t \r \n \f \x0B) | [\t\n\r\f\x0B] |
\S | 非空白字符 | [^\t\n\r\f\x0B] |
. | 任意字符(除換行符,除非開啟 DOTALL) | - |
\\. | 字面點號 | - |
\ | 轉義字符 | - |
Java 字符串中雙重轉義:"\\d+" 代表正則 \d+。
三、 量詞(貪婪/懶惰/佔有)
| 貪婪 | 懶惰 | 佔有 | 含義 |
* | *? | *+ | 0 次或多次 |
+ | +? | ++ | 1 次或多次 |
? | ?? | ?+ | 0 次或 1 次 |
{n} | {n}? | {n}+ | 恰好 n 次 |
{n,} | {n,}? | {n,}+ | 至少 n 次 |
{n,m} | {n,m}? | {n,m}+ | n 到 m 次 |
貪婪優先匹配更多,懶惰優先匹配更少,佔有不回溯(性能最優,慎用)。
四、 字符類與範圍
[abc]:a 或 b 或 c
[a-z]:a 到 z 範圍(按 Unicode 碼點)
[a-zA-Z0-9]:多範圍組合
[^abc]:排除字符類
[a-z&&[^bc]]:交集(a-z 但排除 b,c)
五、 分組、捕獲與反向引用
| 語法 | 說明 | 示例 |
(...) | 捕獲組,可通過 group(1) 獲取 | (\d{4})-(\d{2}) 匹配日期 |
(?:...) | 非捕獲組,不佔用組編號 | (?:\d{3})+ |
\1, \2 | 正則內反向引用第 1、2 組 | (\w+)\s+\1 匹配重複單詞 |
$1, $2 | 替換時引用 | replaceAll("(\\w+)\\s+(\\w+)", "$2 $1") 交換單詞 |
(?...) | 命名捕獲組 (Java 7+) | group("name") |
六、 斷言(零寬斷言)
| 語法 | 名稱 | 含義 |
(?=pattern) | 正向先行斷言 | 後面必須匹配 pattern |
(?!pattern) | 負向先行斷言 | 後面不能匹配 pattern |
(?<=pattern) | 正向後行斷言 | 前面必須匹配 pattern (固定長度) |
(? | 負向後行斷言 | 前面不能匹配 pattern (固定長度) |
七、 常用實戰模式庫
| 場景 | 正則 | 說明 |
| 郵箱 | ^[\\w.-]+@[\\w-]+(\\.[\\w-]+)+$ | 簡易版,RFC 5322 完整版極其複雜 |
| 手機號 (中國大陸) | ^1[3-9]\\d{9}$ | 覆蓋主流運營商號段 |
| 身份證 (18位) | ^\\d{17}[\\dXx]$ | 僅格式校驗,不含校驗碼算法 |
| URL | ^(https?|ftp)://[^\\s/$.?#].[^\\s]*$ | 簡易版 |
| IPv4 | ^((25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d?\\d)$ | 嚴格校驗每段 0-255 |
| 中文字符 | [\\u4e00-\\u9fa5] | 基本漢字區塊 |
| 去除 HTML 標籤 | <[^>]+> | 配合 replaceAll("", "") |
| 提取數字 | \\d+ | 配合 Matcher.find() 循環提取 |
八、 Java API 關鍵用法
// 1. 全匹配
boolean ok = "123".matches("\\d+");
// 2. 編譯復用 (性能優)
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("abc123def");
while (m.find()) { System.out.println(m.group()); } // 123
// 3. 分割
String[] arr = "a,b;c".split("[,;]");
// 4. 替換
String res = "a1b2c".replaceAll("\\d", "#"); // a#b#c
// 5. 分組提取
Matcher m2 = Pattern.compile("(\\d{4})-(\\d{2})").matcher("2023-12");
if (m2.matches()) { System.out.println(m2.group(1)); } // 2023
九、 性能優化提示
- 預編譯
Pattern 復用,避免重複編譯;
- 優先使用具體字符類代替
.;
- 避免嵌套量詞導致災難性回溯(如
(a+)+);
- 長文本用
Matcher.find() 迭代,而非 matches();
- 固定前綴模式(如
^prefix)可顯著加速失敗匹配。
總結
正則表達式強大但易寫成「寫時讀懂、過後難讀」的代碼。建議:
✅ 複雜正則加註釋((?x) 模式或外部文檔);
✅ 關鍵業務(如驗證器)編寫單元測試覆蓋邊界;
✅ 性能敏感場景進行基準測試。
收藏本手冊,下次寫正則不再查文檔!
- 上一篇文章: Hibernate "detached entity passed to persist" 錯誤根因與解決方案
- 下一篇文章: Java String 核心 API 速查與最佳實踐:從基礎操作到性能陷阱
Copyright ©
程式碼之家 All Rights Reserved