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

Java 正則表達式語法詳解:Pattern、Matcher 核心 API 與實戰技巧

     編輯:Java 相關知識

前言

正則表達式是處理字符串匹配、提取、替換、分割的利器。Java 通過 java.util.regex 包提供 Pattern(編譯後的模式)、Matcher(匹配引擎)兩大核心類,支援 Perl 風格語法。本文系統梳理語法元字符、分組捕獲、貪婪/非貪婪模式、常用 API,並給出典型實戰場景代碼。

一、核心類與基本流程

// 1. 編譯模式(線程安全,可重用)
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); // 忽略大小寫

// 2. 創建匹配器(非線程安全,每次匹配 new)
Matcher matcher = pattern.matcher(input);

// 3. 執行匹配操作
boolean found = matcher.find();        // 部分匹配,尋找下一個
boolean matches = matcher.matches();   // 整體匹配
boolean looking = matcher.lookingAt(); // 從開頭匹配

最佳實踐:Pattern 為不可變線程安全,建議定義為 static final 常量複用;Matcher 有狀態,不可共享。

二、語法元字符速查表

類別符號說明示例
字符類.任意單字符(除換行)a.c 匹配 abc、axc
\d數字 [0-9]\d{3} 三位數
\w單詞字符 [a-zA-Z0-9_]\w+ 匹配標識符
量詞(貪婪)*0 次或多次 {0,}ab*c 匹配 ac、abc、abbc
+1 次或多次 {1,}\d+ 至少一位數字
?0 次或 1 次 {0,1}colou?r 匹配 color/colour
量詞(精確){n}恰好 n 次\d{11} 手機號長度
{n,}至少 n 次\w{6,} 密碼最短 6 位
{n,m}n 到 m 次\d{3,5} 3-5 位數字
量詞(非貪婪)*? +? ?? {n,m}?儘可能少匹配.*? 匹配最短字符串
邊界^行首(多行模式下)^Start
$行尾End$
\b單詞邊界\bcat\b 單詞 cat
分組與引用()捕獲組,編號 1,2...(\d{4})-(\d{2})
(?:)非捕獲組(?:\d{3}){2} 不佔組號
\1 \2反向引用(\w+)\s+\1 重複單詞
斷言(?=)正向前瞻\w+(?=\d) 後面跟數字的單詞
(?!)負向前瞻\w+(?!\d) 後面不跟數字
(?<=) (?正/負向後顧(?<=\$)\d+ $ 後的數字
或運算|分支cat|dog 貓或狗
字符類[]集合[aeiou] 元音
排除類[^]非集合[^0-9] 非數字

三、Pattern 編譯標誌

Pattern.CASE_INSENSITIVE   // 忽略大小寫 (?i)
Pattern.MULTILINE          // 多行模式 ^$ 匹配行首尾 (?m)
Pattern.DOTALL             // . 匹配含換行 (?s)
Pattern.UNICODE_CASE       // Unicode 大小寫折疊 (?u)
Pattern.COMMENTS           // 允許註解和空白 (?x)
Pattern.UNICODE_CHARACTER_CLASS // \w \d 等支援 Unicode (?U)

可組合:Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE)

四、Matcher 核心 API 實戰

1. 提取分組內容

String text = "User: alice, Id: 1001; User: bob, Id: 1002";
Pattern p = Pattern.compile("User: (\\w+), Id: (\\d+)");
Matcher m = p.matcher(text);
while (m.find()) {
    String name = m.group(1); // 分組 1
    String id = m.group(2);   // 分組 2
    System.out.println(name + " -> " + id);
}
// 輸出: alice -> 1001, bob -> 1002

2. 替換操作

// 簡單替換所有數字為 *
String masked = text.replaceAll("\\d", "*"); // 內部用 Pattern/Matcher

// 進階替換:用分組內容構建新字符串
String swapped = m.replaceAll("ID=$2, Name=$1"); // 使用 $n 引用分組
// 或使用函數式替換
String custom = p.matcher(text).replaceAll(mr -> 
    "【" + mr.group(1).toUpperCase() + "】");

3. 分割字符串

String csv = "apple, banana; orange|pear";
// 按多種分隔符分割
String[] fruits = csv.split("[,;|]\\s*");
// 結果: [apple, banana, orange, pear]

4. 校驗整體匹配

// 手機號校驗
boolean valid = Pattern.matches("1[3-9]\\d{9}", "13800138000"); // true
// 郵箱簡易校驗
boolean emailOk = Pattern.matches("^[\\w.-]+@[\\w.-]+\\.\\w{2,}$", "test@example.com");

五、高級技巧與避坑指南

1. 非貪婪模式解決「過度匹配」

String html = "
Hello
World
"; // 貪婪:匹配整個字符串 Pattern.compile("
.*
").matcher(html).find(); //
Hello
World
// 非貪婪:匹配單個標籤 Pattern.compile("
.*?
").matcher(html).find(); //
Hello

2. 預編譯 Pattern 提升效能

// 錯誤:循環中重複編譯
for (String s : list) { if (s.matches("\\d+")) ... }

// 正確:靜態常量複用
private static final Pattern DIGITS = Pattern.compile("\\d+");
for (String s : list) { if (DIGITS.matcher(s).matches()) ... }

3. 正則注入風險

用戶輸入直接拼接進正則可能導致 ReDoS(正則拒絕服務)或邏輯繞過。嚴禁:Pattern.compile(userInput)。需對用戶輸入用 Pattern.quote() 轉義,或使用白名單校驗。

4. 後顧斷言固定寬度限制

Java 不支援不定寬度後顧斷言:(?<=ab*) 報錯。需改寫為定寬或用其他邏輯。

六、常用正則模式庫

場景正則說明
手機號(大陸)^1[3-9]\\d{9}$11 位,以 1 開頭,第二位 3-9
身份證 18 位^\\d{17}[\\dXx]$簡易版,嚴格需校驗校驗碼
Email^[\\w.-]+@[\\w.-]+\\.\\w{2,}$通用簡易版
URL^https?://[\\w.-]+(?:\\.[\\w.-]+)+(?:[/?#][^\\s]*)?$HTTP/HTTPS
IPv4^((25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d?\\d)$精確校驗
中文字符[\\u4e00-\\u9fa5]基本漢字區塊
日期 yyyy-MM-dd^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$格式校驗,邏輯合法性需代碼判斷
密碼強度^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$大小寫+數字+特殊字符 8 位以上

七、總結

Java 正則表達式通過 Pattern/Matcher 提供強大的字符串處理能力。掌握核心語法、量詞貪婪性、分組捕獲、斷言、編譯標誌,並養成預編譯 Pattern、警惕 ReDoS、善用非貪婪模式的習慣,能高效解決 95% 的文本解析需求。複雜業務建議結合 String 原生方法、第三方庫(如 Apache Commons Lang StringUtils)協同使用。

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