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

Java 正則表達式實戰:字符串匹配、提取、替換與分割完整指南

     編輯:Java 相關知識

前言

面對「檢查字符串是否包含某些字符」、「提取日誌中的 IP 和時間」、「脫敏手機號」、「按多種分隔符分割」等需求,手寫 if/for/charAt 不僅繁瑣易錯,還難以應對變化。Java java.util.regex 將「匹配規則」封裝為 Pattern 對象,配合 Matcher 引擎,實現聲明式字符串處理。本文通過遞進式案例,展示從簡單匹配到複雜提取替換的完整實戰流程。

一、基礎入門:從手寫循環到正則思維

場景:檢查字符串是否包含 'y' 或 'f'

傳統寫法:

String str = "For my money...";
boolean found = false;
for (int i = 0; i < str.length(); i++) {
    char c = str.charAt(i);
    if (c == 'y' || c == 'f') { found = true; break; }
}

正則寫法:

Pattern p = Pattern.compile("[yf]"); // 字符類:y 或 f
boolean found = p.matcher(str).find(); // 一行搞定

思維轉變:不關心「怎麼遍歷」,只描述「長什麼樣」。

二、核心三步驟模板

// 1. 寫正則字符串
String regex = "正則表達式";

// 2. 編譯成 Pattern(建議靜態常量複用)
Pattern pattern = Pattern.compile(regex);

// 3. 創建 Matcher 執行操作
Matcher matcher = pattern.matcher(targetString);

// 4. 根據需求調用不同方法
matcher.find();      // 部分匹配/查找下一個
matcher.matches();   // 整體匹配
matcher.group(1);    // 獲取分組內容
matcher.replaceAll(replacement); // 替換
pattern.split(input); // 分割

三、實戰案例庫

1. 忽略大小寫匹配

Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
// 或內嵌標誌
Pattern p2 = Pattern.compile("(?i)java");

2. 提取鍵值對:key=value 格式

String config = "host=localhost port=8080 timeout=30";
Pattern p = Pattern.compile("(\\w+)=(\\S+)");
Matcher m = p.matcher(config);
while (m.find()) {
    System.out.println(m.group(1) + " -> " + m.group(2));
}
// host -> localhost, port -> 8080, timeout -> 30

3. 提取括號/引號內容

String log = "User[alice] login from IP(192.168.1.1) at '2024-06-15 10:30'";
Pattern p = Pattern.compile("[\\[\\(']([^\\]\\')]+[\\]\\')]"); // 簡化示例
// 更穩健:分別處理不同括號
Pattern bracket = Pattern.compile("\\[([^\\]]+)\\]");
Pattern paren = Pattern.compile("\\(([^)]+)\\)");
Pattern quote = Pattern.compile("'([^']+)'");

4. 手機號脫敏:中間 4 位替換為 ****

String phone = "13800138000";
String masked = phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
// 結果: 138****8000
// 解析:分組 1=前3位,分組 2=後4位,替換模板 $1****$2

5. HTML 標籤清洗(簡易版)

String html = "

Hello World

"; String text = html.replaceAll("<[^>]+>", ""); // 移除所有標籤 // 結果: Hello World // 注意:複雜 HTML 請用 Jsoup 等專業解析器

6. 多種分隔符分割

String line = "apple, banana; orange|pear  grape";
String[] fruits = line.split("[,;|]\\s*"); // 正則分割
// [apple, banana, orange, pear, grape]

7. 驗證整體格式:密碼強度

String pwdRegex = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$";
boolean strong = Pattern.matches(pwdRegex, "Abc12345@"); // true
// 解析:4 個正向前瞻分別檢查小寫、大寫、數字、特殊符號

8. 日期格式轉換:yyyy-MM-dd -> MM/dd/yyyy

String date = "2024-06-15";
String converted = date.replaceAll("(\\d{4})-(\\d{2})-(\\d{2})", "$2/$3/$1");
// 結果: 06/15/2024

9. 非貪婪匹配:提取最短標籤內容

String html = "
Hello
World
"; // 貪婪 .* 匹配整個字符串 // 非貪婪 .*? 匹配單個標籤 Pattern p = Pattern.compile("
(.*?)
"); Matcher m = p.matcher(html); while (m.find()) System.out.println(m.group(1)); // Hello // World

10. 函數式替換:動態計算替換值

String text = "price: 100, discount: 20";
Pattern p = Pattern.compile("(\\d+)");
String result = p.matcher(text).replaceAll(mr -> {
    int val = Integer.parseInt(mr.group());
    return String.valueOf(val * 2); // 所有數字乘 2
});
// 結果: price: 200, discount: 40

四、效能優化與最佳實踐清單

  1. Pattern 靜態常量複用:編譯正則開銷大,定義為 private static final Pattern P = Pattern.compile(...)。
  2. 優先用 String 方法:簡單替換 str.replace("old", "new")、分割 str.split(",") 內部已優化,無需手動 Pattern。
  3. 避免災難性回溯:警惕 (a+)+、(a|aa)* 等嵌套量詞,輸入 aaaaaaaaaaaa! 會導致指數級回溯(ReDoS)。
  4. 用戶輸入轉義:Pattern.quote(userInput) 將任意字符串視為字面量,防止注入。
  5. 預編譯標誌常量:Pattern.CASE_INSENSITIVE | Pattern.DOTALL 組合使用。
  6. 複雜 HTML/XML/JSON 勿用正則:改用 Jsoup、DOM4J、Jackson 等專業解析器。

五、總結

Java 正則表達式以 Pattern/Matcher 為核心,提供「聲明規則、引擎執行」的強大範式。掌握字符類、量詞、分組捕獲、非貪婪、斷言、替換模板 $n、函數式替換等核心技能,配合預編譯複用、ReDoS 防範、轉義用戶輸入工程化習慣,能優雅高效解決絕大多數文本處理場景。記住:正則是瑞士軍刀,不是萬能鑰匙——複雜結構化文本請用專用解析器。

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