正則元字符完整語法表
量詞與貪婪/非貪婪模式
| 語法 | 名稱 | 匹配次數 | 貪婪性 | 示例 |
* | 零或多 | 0~n | 貪婪 | ab*c 匹配 "ac", "abc", "abbc" |
+ | 一或多 | 1~n | 貪婪 | ab+c 匹配 "abc", "abbc" |
? | 零或一 | 0~1 | 貪婪 | ab?c 匹配 "ac", "abc" |
{n} | 固定 n 次 | n | 貪婪 | a{3} 匹配 "aaa" |
{n,} | 至少 n 次 | n~∞ | 貪婪 | a{2,} 匹配 "aa", "aaa" |
{n,m} | n 到 m 次 | n~m | 貪婪 | a{1,3} 匹配 "a", "aa", "aaa" |
*? | 零或多 | 0~n | 非貪婪 | ab*?c 在 "abbbc" 中匹配 "abc" |
+? | 一或多 | 1~n | 非貪婪 | ab+?c 在 "abbbc" 中匹配 "abc" |
?? | 零或一 | 0~1 | 非貪婪 | 極少使用 |
{n,}? | 至少 n 次 | n~∞ | 非貪婪 | 盡可能少匹配 |
{n,m}? | n 到 m 次 | n~m | 非貪婪 | 盡可能少匹配 |
定位符與邊界
| 語法 | 含義 | 示例 |
^ | 字符串開始(多行模式下行首) | ^Hello 匹配 "Hello world" |
$ | 字符串結束(多行模式下行尾) | world$ 匹配 "Hello world" |
\b | 單詞邊界 | \bcat\b 匹配 "cat" 不匹配 "category" |
\B | 非單詞邊界 | \Bcat\B 匹配 "category" 中的 "cat" |
\A | 字符串絕對開頭 | 不受多行模式影響 |
\Z | 字符串絕對結尾 | 不受多行模式影響 |
\z | 字符串絕對結尾(不含末尾換行) | 最嚴格結尾 |
\G | 上次匹配結束位置 | 配合 find() 連續匹配 |
字符類與預定義字符類
| 語法 | 含義 | 等價形式 |
. | 任意字符(除換行符) | [\s\S] 匹配含換行 |
\d | 數字 | [0-9] |
\D | 非數字 | [^0-9] |
\s | 空白字符 | [ \t\n\r\f\v] |
\S | 非空白字符 | [^ \t\n\r\f\v] |
\w | 單詞字符 | [a-zA-Z0-9_] (Unicode 感知) |
\W | 非單詞字符 | [^a-zA-Z0-9_] |
[abc] | 字符集合 | 匹配 a/b/c 任一 |
[^abc] | 負向字符集合 | 匹配非 a/b/c |
[a-z] | 字符範圍 | a 到 z |
[^a-z] | 負向範圍 | 非 a-z |
分組、捕獲與引用
| 語法 | 名稱 | 說明 |
(pattern) | 捕獲組 | 匹配並編號,可用 $1、\1 反向引用 |
(?:pattern) | 非捕獲組 | 僅分組不捕獲,效能更好 |
(?<name>pattern) | 命名捕獲組 | Java 7+ 支援,${name} 引用 |
\n | 反向引用 | 引用第 n 個捕獲組 |
\k<name> | 命名反向引用 | 引用命名捕獲組 |
斷言(零寬斷言/環視)
| 語法 | 名稱 | 方向 | 條件 | 示例 |
(?=pattern) | 正向肯定預查 | 向右 | 後面匹配 pattern | Windows(?=95|98) 匹配 "Windows95" 中的 "Windows" |
(?!pattern) | 正向否定預查 | 向右 | 後面不匹配 pattern | Windows(?!95|98) 匹配 "Windows3.1" 中的 "Windows" |
(?<=pattern) | 反向肯定預查 | 向左 | 前面匹配 pattern | (?<=95|98)Windows 匹配 "95Windows" 中的 "Windows" |
(?<!pattern) | 反向否定預查 | 向左 | 前面不匹配 pattern | (?<!95|98)Windows 匹配 "3.1Windows" 中的 "Windows" |
關鍵特性:斷言不消耗字符,匹配寬度為零,僅檢查條件。
轉義與特殊構造
| 語法 | 說明 |
\ | 轉義元字符:\. 匹配字面點,\\ 匹配反斜槓 |
\cX | 控制字符:\cM = 回車符 |
\xNN | 十六進制:\x41 = 'A' |
\uNNNN | Unicode:\u00A9 = © |
\NNN | 八進制:\040 = 空格 |
\Q...\E | 字面量區塊:\Q.*+\E 匹配字面 ".*+" |
模式修飾符(嵌入模式)
| 語法 | 效果 | 等價 Flag |
(?i) | 忽略大小寫 | Pattern.CASE_INSENSITIVE |
(?m) | 多行模式(^$ 匹配行首尾) | Pattern.MULTILINE |
(?s) | 單行模式(. 匹配換行) | Pattern.DOTALL |
(?x) | 註釋模式(忽略空白、支援 # 註釋) | Pattern.COMMENTS |
(?U) | Unicode 感知 | Pattern.UNICODE_CHARACTER_CLASS |
(?-i) | 關閉忽略大小寫 | 局部關閉 |
組合示例:(?im)^pattern$ 忽略大小寫+多行模式。
常用實戰模式庫(可直接複製使用)
身份證號(中國大陸 18 位)
^(\d{6})(18|19|20)?(\d{2})([01]\d)([0123]\d)(\d{3})(\d|X|x)?$
解析:地址碼(6) + 年份(4) + 月(2) + 日(2) + 順序碼(3) + 校驗碼(1)
手機號(主流號段)
^1[3-9]\d{9}$
涵蓋 13-19 開頭,11 位數字。
郵箱地址(RFC 5322 簡化版)
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
URL(HTTP/HTTPS)
^https?://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
IPv4 地址
^((25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(25[0-5]|2[0-4]\d|[01]?\d?\d)$
強密碼(8-20位,含大小寫數字特殊符號)
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*]).{8,20}$
中文字符
^[\u4e00-\u9fa5]+$
日期(YYYY-MM-DD,含閏年簡易校驗)
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
Java 代碼最佳實踐
1. 編譯複用 Pattern
// 靜態常量編譯一次,多次復用
private static final Pattern EMAIL_PATTERN = Pattern.compile(
"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
);
public boolean isValidEmail(String email) {
return EMAIL_PATTERN.matcher(email).matches();
}
2. Matcher 核心方法
| 方法 | 用途 |
matches() | 整串完全匹配 |
find() | 尋找子串匹配,配合 start()/end()/group() |
find(int start) | 從指定位置開始尋找 |
group(int group) | 獲取指定捕獲組內容 |
group(String name) | 獲取命名捕獲組內容 |
replaceAll(String) | 替換所有匹配 |
replaceFirst(String) | 替換首個匹配 |
results() | Java 9+ 返回 Stream<MatchResult> |
3. 分組提取實戰
String text = "User: zhangsan, Email: zhangsan@example.com";
Pattern p = Pattern.compile("User:\\s*(\\w+),\\s*Email:\\s*([\\w.]+@[\\w.]+)");
Matcher m = p.matcher(text);
if (m.find()) {
System.out.println("用戶名:" + m.group(1)); // zhangsan
System.out.println("郵箱:" + m.group(2)); // zhangsan@example.com
}
4. 命名捕獲組(Java 7+)
Pattern p = Pattern.compile("(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})");
Matcher m = p.matcher("2024-01-15");
if (m.matches()) {
System.out.println(m.group("year")); // 2024
System.out.println(m.group("month")); // 01
System.out.println(m.group("day")); // 15
}
效能優化與避坑指南
災難性回溯
// 危險模式:嵌套量詞 + 非匹配輸入
String dangerous = "(a+)+b";
String input = "aaaaaaaaaaaaaaaaaaaaac"; // 無 b 結尾
// 回溯次數指數級爆炸,導致 CPU 100% 假死
解決:使用佔有優先量詞 (a++)+b 或原子組 (?>a+)+b,或重寫邏輯避免嵌套量詞。
預編譯與緩存
Pattern.compile() 較重,務必靜態常量復用
- Java 內部緩存最近 256 個 Pattern(
PatternCache),但不應依賴
Unicode 支援
// Java 8+ 預設 Unicode 感知,\w 匹配中文等
// 強制開啟:Pattern.compile(regex, Pattern.UNICODE_CHARACTER_CLASS)
總結
正則表達式是文本處理的利器,掌握核心語法分類——量詞、定位、字符類、分組、斷言、修飾符,配合 Pattern/Matcher API,即可應對 95% 匹配提取場景。記住:預編譯復用、警惕回溯、善用非貪婪與斷言,寫出高效可維護的正則。