在早期 Java 版本(JDK 1.4 之前)處理字串搜尋、比對、替換時,開發者只能依靠 charAt()、for 迴圈與 if 判斷,程式碼冗長且難以維護。隨著 java.util.regex 套件的引入,我們得以使用「模式」物件封裝比對邏輯,大幅簡化程式碼並提升可讀性。
假設要檢查字串中是否包含 'y' 或 'f',傳統寫法如下:
class Test {
public static void main(String args[]) {
String str = "For my money, the important thing about the meeting was bridge-building";
char x = 'y';
char y = 'f';
boolean result = false;
for (int i = 0; i < str.length(); i++) {
char z = str.charAt(i);
if (x == z || y == z) {
result = true;
break;
} else {
result = false;
}
}
System.out.println(result);
}
}
這種方式在面對「含 is」、「含 thing 或 ting」等複雜需求時,程式碼會變得極其龐大且難以擴充。
JDK 1.4 引入兩個核心類別:
final 類別,建構子為 private,透過靜態 compile() 取得實例)。find()、matches()、replaceAll() 等豐富方法。import java.util.regex.*;
class Regex1 {
public static void main(String args[]) {
String str = "For my money, the important thing about the meeting was bridge-building";
String regEx = "a|f"; // 表示 a 或 f
Pattern p = Pattern.compile(regEx); // 編譯模式
Matcher m = p.matcher(str); // 建立比對器
boolean result = m.find(); // 執行搜尋
System.out.println(result); // true
}
}
忽略大小寫:Pattern.compile(regEx, Pattern.CASE_INSENSITIVE)
無參考鏈結寫法:boolean result = Pattern.compile(regEx).matcher(str).find();
| 符號 | 意義 | 等價大括號寫法 |
|---|---|---|
* | 零次或多次 | {0,} |
+ | 一次或多次 | {1,} |
? | 零次或一次 | {0,1} |
{n} | 恰好 n 次 (n>0) | — |
{n,m} | 最少 n 次、最多 m 次 (0<n<m) | — |
{n,} | 最少 n 次 | — |
ab* 比對 a、ab、abb、abbb…ab+ 比對 ab、abb、abbb…(等價 abb*)or? 比對 o、or| 符號 | 名稱 | 說明 |
|---|---|---|
| | 或 | 例如 a|f 表示 a 或 f |
. | 句點 | 比對任意單一字元(含空白、Tab、換行) |
[] | 方括號 | 字元集合,僅比對括號內字元,如 [aeio] |
() | 圓括號 | 分組,視為單一整體,可搭配量詞,如 (ab)+ |
- | 連字符 | 表示範圍,如 [0-9]、[a-z] |
^ | 否定 | 在 [] 內表示排除,如 [^a] 非 a 字元 |
// 1. (a|b){2} → aa、ab、ba、bb
// 2. a[abc]b → aab、abb、acb
// 3. . → 任意單一字元
// 4. a. → aa、ax、a1…
// 5. d[^j]a → daa、d9a…(排除 dja)
// 6. [d-g][ac]c → dac、ecc、fcc、gcc、dcc…
Matcher.replaceAll(String replacement) 可將所有符合模式的子字串替換為指定字串;傳入空字串 "" 即為刪除。
import java.util.regex.*;
class Regex1 {
public static void main(String args[]) {
String regEx = "a+"; // 一個或多個 a
String str = "abbbaaa an banana hhaana";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(str);
String s = m.replaceAll("⊙⊙"); // 替換
System.out.println(s); // 輸出:⊙⊙bbb⊙⊙ ⊙⊙n b⊙⊙n⊙⊙ h⊙⊙n⊙⊙
}
}
import java.util.regex.*;
class Regex1 {
public static void main(String args[]) {
String str = "abcaccbcbaacabccaa";
// 先刪除 ac 或 ca
String regEx = "(ac)|(ca)";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(str);
String s = m.replaceAll(""); // 結果:abcbbcbaabccaa → 實際為 bbcbbbaa
// 再刪除 ab 或 ba
regEx = "(ab)|(ba)";
p = Pattern.compile(regEx);
s = p.matcher(s).replaceAll("");
System.out.println(s); // 最終輸出:ccbcca
}
}
java.util.regex 僅包含 Pattern 與 Matcher 兩個核心類別,但方法極豐富,建議參考 JDK 文件深入學習。String 類別的 split()、matches() 等方法底層同樣仰賴正則表達式。