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

Java 正則表達式實戰指南:Pattern/Matcher 核心 API、常用規則速查與效能優化

     編輯:Java 相關知識

正則表達式是文本處理的利器。本文基於 java.util.regex 套件,系統講解 **Pattern 編譯與快取、Matcher 三大匹配模式、分組捕獲與替換、常用字符類/量詞/邊界/斷言速查表、貪婪/懶惰/獨佔模式、效能優化與災難性回溯防範**,附完整工具類與實戰案例。

一、核心類與三種匹配模式


Pattern pattern = Pattern.compile(regex);           // 編譯 (建議預編譯快取)
Matcher matcher = pattern.matcher(input);           // 建立匹配器

// 1. 完全匹配
boolean full = matcher.matches();                   // 整個輸入必須匹配

// 2. 尋找子串 (可多次調用)
while (matcher.find()) {                            // 找到下一個匹配
    String group = matcher.group();                 // 整個匹配
    String g1 = matcher.group(1);                   // 第 1 組
    int start = matcher.start(); int end = matcher.end();
}

// 3. 部分匹配 (從開頭開始,不要求結尾)
boolean looking = matcher.lookingAt();

二、常用正則語法速查表

類別符號說明範例
字符類.任意字符 (除換行)a.c 匹配 abc, axc
\d數字 [0-9]\d{3} 三位數
\w單詞字符 [a-zA-Z0-9_]\w+ 單詞
\s空白字符 (空格/製表/換行)\s* 任意空白
[abc]字符集合[aeiou] 元音
[^abc]排除字符集合[^0-9] 非數字
量詞*0 或多次 (貪婪)ab*c ac, abc, abbc
+1 或多次\d+ 至少一位數
?0 或 1 次colou?r color/colour
{n}恰好 n 次\d{4} 四位數
{n,m}n 到 m 次\d{3,5} 3~5 位數
邊界/斷言^ $行首/行尾 (多行模式)^Start
\b單詞邊界\bcat\b 整詞 cat
(?=...) (?!...)正向/負向前瞻 (零寬)\d+(?=元) 數字後跟「元」
分組(...)捕獲組 (可反向引用 \1)(\d{4})-(\d{2}) 年-月
非捕獲組(?:...)僅分組不捕獲(?:\d{3})-

三、貪婪 vs 懶惰 vs 獨佔量詞


String input = "
Hello
World
"; // 貪婪 (預設) - 匹配盡可能多 Pattern.compile("
.*
").matcher(input).group(); //
Hello
World
// 懶惰 (? 後綴) - 匹配盡可能少 Pattern.compile("
.*?
").matcher(input).group(); //
Hello
// 獨佔 (+ 後綴) - 不回溯,失敗即失敗 Pattern.compile("
.*+
").matcher(input); // 無匹配 (.*+ 吞掉所有字符導致
無法匹配)

四、分組捕獲與替換實戰


String text = "訂單號: ORD-20240520-001, 金額: $1,234.56";
// 1. 提取所有數字
Matcher m = Pattern.compile("\\d+").matcher(text);
while (m.find()) System.out.println(m.group()); // 20240520, 001, 1, 234, 56

// 2. 替換:隱藏金額後四位
String masked = text.replaceAll("(\\$[\\d,]+)\\.\\d{2}", "$1.**"); // $1,234.**

// 3. 使用 Matcher.appendReplacement/Tail 精細控制
StringBuilder sb = new StringBuilder();
Matcher m2 = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})").matcher("2024-05-20");
while (m2.find()) {
    m2.appendReplacement(sb, "$3/$2/$1"); // 20/05/2024
}
m2.appendTail(sb);
System.out.println(sb); // 20/05/2024

五、Pattern 編譯旗標


Pattern.CASE_INSENSITIVE      // 忽略大小寫 (?i)
Pattern.MULTILINE             // ^$ 匹配行首行尾 (?m)
Pattern.DOTALL                // . 匹配含換行 (?s)
Pattern.UNICODE_CHARACTER_CLASS // \w \d \s 支援 Unicode (?U)
Pattern.COMMENTS              // 允許註解與空白 (?x)
Pattern.UNIX_LINES            // 僅 \n 視為行終結符 (?d)

// 組合使用
Pattern.compile("(?i)(?m)^error.*$"); // 忽略大小寫、多行模式匹配以 error 開頭的行

六、效能優化與災難性回溯防範

  • ✅ **預編譯 Pattern**:靜態常量或緩存,避免重複編譯開銷。
  • ✅ **避免嵌套量詞**:(a+)+、(a*)* 易觸發指數級回溯。
  • ✅ **使用獨佔量詞 / 原子組**:(?>...) 或 *+ 切斷回溯路徑。
  • ✅ **錨定開頭 ^**:若知曉匹配位置,加上 ^ 大幅縮小搜索空間。
  • ✅ **具體化字符類**:用 [a-z] 替代 .,減少嘗試分支。
  • ✅ **限制輸入長度**:前端/網關層限制請求體大小,防止 ReDoS 攻擊。

七、實用工具類:RegexUtils


public final class RegexUtils {
    private static final Map CACHE = new ConcurrentHashMap<>();
    private static final int MAX_CACHE = 256;

    public static Pattern getPattern(String regex) {
        return CACHE.computeIfAbsent(regex, Pattern::compile);
    }

    public static boolean isMatch(String regex, String input) {
        return getPattern(regex).matcher(input).matches();
    }

    public static boolean contains(String regex, String input) {
        return getPattern(regex).matcher(input).find();
    }

    public static List findAll(String regex, String input) {
        List list = new ArrayList<>();
        Matcher m = getPattern(regex).matcher(input);
        while (m.find()) list.add(m.group());
        return list;
    }

    public static String replaceFirst(String regex, String replacement, String input) {
        return getPattern(regex).matcher(input).replaceFirst(replacement);
    }

    public static String replaceAll(String regex, String replacement, String input) {
        return getPattern(regex).matcher(input).replaceAll(replacement);
    }

    public static String[] split(String regex, String input, int limit) {
        return getPattern(regex).split(input, limit);
    }
}

熟練掌握 Java 正則 API 與優化原則,能高效解決 90% 以上的文本解析、驗證、清洗需求。

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