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

Java 正則表達式完整指南:Pattern 與 Matcher 核心用法、常用語法速查表

     編輯:Java 綜合教學

Java 正則表達式核心 API 快速上手

Java 正則表達式處理主要依賴 java.util.regex 套件中的兩個核心類別:Pattern(編譯後的正則模式)與 Matcher(針對輸入字串執行匹配的引擎)。掌握其標準用法與簡寫用法,能大幅提升字串解析、驗證、替換等任務的開發效率。

一、Pattern 與 Matcher 標準使用流程

1. 典型三步驟用法

// 1. 將正則字串編譯為 Pattern 物件(可重複使用、執行緒安全)
Pattern p = Pattern.compile("a*b");

// 2. 使用 Pattern 建立 Matcher 物件,綁定待匹配字串
Matcher m = p.matcher("aaaaab");

// 3. 執行匹配操作
boolean b = m.matches(); // 返回 true,整個字串符合 "a*b" 模式

2. 單次使用簡寫:Pattern.matches()

若正則表達式僅需使用一次,可直接呼叫靜態方法,自動完成編譯與匹配:

boolean b = Pattern.matches("a*b", "aaaaab"); // 返回 true

3. 關鍵特性提醒

  • Pattern 是不可變類別,編譯後可安全地在多執行緒間共用。
  • Matcher 非執行緒安全,每個執行緒應建立自己的實例。

二、Matcher 常用方法速查

方法說明回傳值範例
matches()嘗試將整個目標字串與模式匹配true / false
find()掃描目標字串,尋找下一個符合模式的子串true / false
group()返回上一次成功匹配的子串(整組匹配)匹配到的字串
group(int group)返回指定捕獲組的內容(group 0 為整組)捕獲組字串
start()返回上一次匹配子串在目標字串中的起始索引int 索引值
end()返回上一次匹配子串的結束索引 + 1int 索引值
replaceAll(String replacement)將所有匹配子串替換為指定字串新字串
replaceFirst(String replacement)僅替換第一個匹配子串新字串

實戰範例:提取所有數字

String text = "訂單號:20231015,金額:3580 元,會員 ID:VIP888";
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher(text);

while (m.find()) {
    System.out.printf("找到:%s 位置[%d, %d)%n", m.group(), m.start(), m.end());
}
/* 輸出:
找到:20231015 位置[5, 13)
找到:3580 位置[17, 21)
找到:888 位置[30, 33)
*/

三、正則表達式核心語法速查表

以下整理最常用的元字元、量詞、字元類別、邊界與分組語法,建議收藏備查。

1. 字元類別

語法說明範例匹配
.任意單一字元(除換行符)"a", "1", "@"
\d數字 [0-9]"5"
\D非數字 [^0-9]"A"
\w單字字元 [a-zA-Z0-9_]"z", "9", "_"
\W非單字字元"@", "#"
\s空白字元(空格、Tab、換行)" "
\S非空白字元"x"
[abc]字元集合:a 或 b 或 c"a"
[^abc]排除字元集合"d"
[a-z]字元範圍"m"

2. 量詞(貪婪/懶惰/佔有)

貪婪懶惰佔有說明
**?*+0 次或多次
++?++1 次或多次
????+0 次或 1 次
{n}{n}?{n}+恰好 n 次
{n,}{n,}?{n,}+至少 n 次
{n,m}{n,m}?{n,m}+n 到 m 次

提示:預設為貪婪模式(盡可能多匹配),在量詞後加 ? 切換為懶惰模式(盡可能少匹配),加 + 為佔有模式(不回溯,效能最佳但功能受限)。

3. 邊界與鍵定

語法說明
^行首(Pattern.MULTILINE 開啟時為每行行首)
$行尾(Pattern.MULTILINE 開啟時為每行行尾)
\b單字邊界(字母/數字/底線與非單字字元之間)
\B非單字邊界
\A字串開頭(不受 MULTILINE 影響)
\z字串結尾(不受 MULTILINE 影響)
\Z字串結尾或結尾換行符之前

4. 分組與反向引用

語法說明範例
(...)捕獲組,可用 group(1) 等取得(\d{4})-(\d{2}) 擷取年、月
(?:...)非捕獲組,僅分組不佔用 group 索引(?:\d{3})?\d{3}-\d{4}
(?<name>...)具名捕獲組(Java 7+),group("name") 取得(?<year>\d{4})
\1, \2...正則內部反向引用前面捕獲組(['\"]).*?\1 匹配成對引號
$1, $2...替換字串中引用捕獲組m.replaceAll("$2-$1")

5. 斷言(零寬斷言)

語法名稱說明
(?=...)正向先行斷言後面必須匹配 ...,不消耗字元
(?!...)負向先行斷言後面不能匹配 ...
(?<=...)正向後行斷言前面必須匹配 ...(固定長度)
(?<!...)負向後行斷言前面不能匹配 ...(固定長度)

6. 常用 Flag(Pattern.compile(regex, flags))

  • Pattern.CASE_INSENSITIVE (?i):忽略大小寫
  • Pattern.MULTILINE (?m):^/$ 匹配每行首尾
  • Pattern.DOTALL (?s):. 匹配含換行符的任意字元
  • Pattern.COMMENTS (?x):允許註釋與空白,提升可讀性
  • Pattern.UNICODE_CASE (?u):配合 CASE_INSENSITIVE 進行 Unicode 標準大小寫折疊

四、進階實戰技巧

1. 字串分割:String.split() 底層即使用 Pattern

String[] parts = "a,b;;c , d".split("\\s*[;,]\\s*");
// 結果:["a", "b", "c", "d"]

2. 驗證完整字串格式(手機號、Email 等)

// 手機號簡易驗證(中國大陸)
String mobileRegex = "^1[3-9]\\d{9}$";
boolean valid = Pattern.matches(mobileRegex, "13812345678"); // true

3. 替換時引用捕獲組:格式化日期

String raw = "20231015";
String formatted = raw.replaceAll("(\\d{4})(\\d{2})(\\d{2})", "$1-$2-$3");
// 結果:"2023-10-15"

4. 具名捕獲組提升可維護性(Java 9+ 建議)

Pattern p = Pattern.compile("(?<year>\\d{4})-(?<month>\\d{2})-(?<day>\\d{2})");
Matcher m = p.matcher("2023-10-15");
if (m.matches()) {
    System.out.println(m.group("year"));  // 2023
    System.out.println(m.group("month")); // 10
    System.out.println(m.group("day"));   // 15
}

五、效能與最佳實踐建議

  1. 預編譯 Pattern 重複使用,避免在迴圈或高頻呼叫中重複 Pattern.compile()。
  2. 優先使用具體字元類別(如 [a-z])而非 .,減少回溯。
  3. 避免巢狀量詞(如 (a*)*),極易導致災難性回溯(ReDoS)。
  4. 長字串匹配使用 find() 迴圈,而非 matches()。
  5. 針對固定前綴/後綴的模式,加上 ^/$ 或 \A/\z 讓引擎快速失敗。
  6. 複雜正則拆解為多個簡單步驟,或使用 Pattern.COMMENTS 加上註釋提升可讀性。

掌握 Java 正則表達式的關鍵在於理解 Pattern 編譯與 Matcher 狀態機 的運作模式,熟練運用分組、斷言、旗標等進階語法,並養成「預編譯、避免回溯、善用捕獲組」的工程習慣。將本文語法表加入書籤,下次遇到字串解析難題時即可快速查閱、精準出擊。

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