在文本處理中,正確匹配換行符與行邊界是常見難點。Java 正則表達式默認單行模式下,^ 和 $ 僅匹配整個輸入字符串的開頭和結尾,而 . 不匹配換行符。啟用 Pattern.MULTILINE 和 Pattern.DOTALL 後,行為發生根本變化。
| 模式 | ^ 匹配位置 | $ 匹配位置 | . 匹配範圍 |
|---|---|---|---|
| 默認 (單行) | 字符串開頭 | 字符串結尾 | 除換行符外任意字符 |
| MULTILINE | 字符串開頭、每行開頭 (換行符後) | 字符串結尾、每行結尾 (換行符前) | 除換行符外任意字符 |
| DOTALL | 字符串開頭 | 字符串結尾 | 任意字符含換行符 |
| MULTILINE | DOTALL | 字符串開頭、每行開頭 | 字符串結尾、每行結尾 | 任意字符含換行符 |
import java.util.regex.Pattern;
public class NLMatch {
public static void main(String[] args) {
String input = "I dream of engines\nmore engines, all day long";
System.out.println("INPUT: " + input);
System.out.println();
String[] patterns = {
"engines.more engines", // . 默認不匹配 \n
"ines\nmore", // 顯式匹配 \n
"engines$" // $ 匹配行尾
};
for (String patt : patterns) {
System.out.println("PATTERN: " + patt);
// 默認模式
boolean found = Pattern.compile(patt).matcher(input).find();
System.out.println("DEFAULT match: " + found);
// 多行 + 單行模式 (DOTALL 讓 . 匹配 \n)
found = Pattern.compile(patt, Pattern.DOTALL | Pattern.MULTILINE)
.matcher(input).find();
System.out.println("Multiline+Dotall match: " + found);
System.out.println();
}
}
}
engines.more engines:默認 false (.不匹配\n),加 DOTALL 後 trueines\nmore:兩種模式均 true (顯式 \n 不受模式影響)engines$:默認 false ($只匹配字符串末尾),加 MULTILINE 後 true (匹配第一行結尾)MULTILINE,配合 ^pattern$ 匹配整行DOTALL,讓 . 真正成爲「任意字符」\n、\r 或 \r\n,不依賴模式標誌,可移植性最強Pattern.DOTALL | Pattern.MULTILINE 可同時獲得「.匹配換行」與「^$匹配行邊界」雙重能力掌握這兩個標誌的組合語義,是編寫健壯、可移植正則表達式的關鍵一步。