正則表達式是文本處理的瑞士軍刀。Java 透過 `java.util.regex` 套件提供強大的正則支援。本文系統整理核心語法、常用模式與最佳實踐,助你高效驗證、提取、替換文本。
| 語法 | 名稱 | 條件 |
(?=...) | 正向前瞻 | 後面匹配 ... |
(?!...) | 負向前瞻 | 後面不匹配 ... |
(?<=...) | 正向後顧 | 前面匹配 ... (固定長度) |
(?<!...) | 負向後顧 | 前面不匹配 ... (固定長度) |
模式標記
// 單行模式:. 匹配含換行
Pattern.compile(regex, Pattern.DOTALL);
// 多行模式:^ $ 匹配每行開頭結尾
Pattern.compile(regex, Pattern.MULTILINE);
// 忽略大小寫
Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
// 註釋模式:忽略空白,允許 # 註釋
Pattern.compile(regex, Pattern.COMMENTS);
// Unicode 感知大小寫
Pattern.compile(regex, Pattern.UNICODE_CASE);
// 組合使用
Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
三、實戰常用模式庫
1. 基礎驗證
// Email (簡化版,RFC 5322 完整版極其複雜)
^[\\w.-]+@[\\w-]+(\\.[\\w-]+)+$
// 手機號 (中國大陸)
^1[3-9]\\d{9}$
// 身份證號 (18位,含校驗碼邏輯需代碼實現)
^[1-9]\\d{5}(19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[\\dXx]$
// IP 地址 (IPv4)
^((25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d?\\d)$
// URL
^(https?|ftp)://[^\\s/$.?#].[^\\s]*$
// 日期 (YYYY-MM-DD)
^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$
2. 提取與解析
// 提取 HTML 標籤屬性
<(\\w+)[^>]*?\\s(\\w+)=["']([^"']*)["']
// 提取 URL 域名
https?://([^/]+)
// 提取 Java 包名/類名
package\\s+([\\w.]+);|class\\s+(\\w+)
// 分割 CamelCase: "UserName" → ["User", "Name"]
(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])
3. 替換與清洗
// 移除 HTML 標籤
html.replaceAll("<[^>]*>", "")
// 多空白合併為單空格
text.replaceAll("\\s+", " ")
// 隱藏手機中間4位
phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")
// 轉義正則特殊字符 (用於字面量匹配)
Pattern.quote(literalString)
四、效能優化黃金法則
- 預編譯複用 Pattern:`Pattern` 線程安全,編譯昂貴,靜態常量或緩存複用。
- 避免過度回溯:慎用嵌套數量詞 `(a+)+`、交替分支中的公共前綴。改用佔有量詞 `++`、`*+` 或原子組 `(?>...)`。
- 錨點前置:模式以 `^` 或 `\A` 開頭,能快速失敗。
- 具體化字符類:用 `[a-f0-9]` 代替 `.`,減少嘗試。
- 非捕獲組:不需反向引用時用 `(?:...)`。
- 適度使用 `find()` 代替 `matches()`:`matches()` 需匹配整串,`find()` 尋找子串更快。
五、進階技巧:Pattern 與 Matcher 進階用法
1. 分組引用替換
// 格式化電話: "1234567890" → "(123) 456-7890"
String formatted = phone.replaceAll("(\\d{3})(\\d{3})(\\d{4})", "($1) $2-$3");
2. 使用 Matcher.appendReplacement/appendTail 精細控制替換
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
// 根據匹配內容動態決定替換字符串
String replacement = computeReplacement(matcher.group());
matcher.appendReplacement(sb, Matcher.quoteReplacement(replacement));
}
matcher.appendTail(sb);
String result = sb.toString();
3. 解析鍵值對 (如 URL 參數、配置檔)
Pattern p = Pattern.compile("(\\w+)=([^&]*)");
Matcher m = p.matcher(queryString);
Map params = new LinkedHashMap<>();
while (m.find()) {
params.put(m.group(1), URLDecoder.decode(m.group(2), "UTF-8"));
}
六、推薦線上測試工具
- Regex101:支援 Java 味道,即時解釋、測試、生成代碼片段。
- RegExr:視覺化高亮、社區模式庫。
- IDE 內建正則測試器 (IntelliJ IDEA: Ctrl+Alt+R / Cmd+Opt+R)。
正則表達式功能強大但「寫時易讀、改時難懂」。建議:複雜正則必加註釋,使用 `Pattern.COMMENTS` 模式或拆分為多行字符串並附上範例輸入/輸出。掌握核心語法與優化原則,讓正則成為你手中得心應手的利器。
- 上一篇文章: JavaWeb 監聽器實戰 (一):監聽 ServletContext 與 HttpSession 生命週期
- 下一篇文章: 複雜 XML 轉 Java 實體實戰:以支付寶回調報文為例
Copyright ©
程式碼之家 All Rights Reserved