Java 正则表达式完全指南:Pattern、Matcher 实战
Java 提供了强大的正则表达式支持。本文详细介绍 Pattern 和 Matcher 类的使用方法。
Pattern 类
Pattern 是正则表达式的编译表示。
编译正则
import java.util.regex.Pattern;
// 编译正则表达式
Pattern pattern = Pattern.compile("^1[3-9]\d{9}$");
// 带标志编译
Pattern pattern = Pattern.compile("hello", Pattern.CASE_INSENSITIVE);
常用标志
| 标志 | 说明 |
|---|---|
| CASE_INSENSITIVE | 忽略大小写 |
| MULTILINE | 多行模式 |
| DOTALL | . 匹配换行符 |
| UNICODE_CASE | Unicode 大小写 |
预编译优化
// ❌ 每次都编译
for (String str : list) {
if (str.matches("^1[3-9]\d{9}$")) {
// ...
}
}
// ✅ 预编译
Pattern pattern = Pattern.compile("^1[3-9]\d{9}$");
for (String str : list) {
if (pattern.matcher(str).matches()) {
// ...
}
}
Matcher 类
Matcher 是对输入字符串进行匹配操作的引擎。
基本用法
Pattern pattern = Pattern.compile("\d+");
Matcher matcher = pattern.matcher("hello123world456");
// 查找所有匹配
while (matcher.find()) {
System.out.println(matcher.group()); // 123, 456
}
常用方法
// 完全匹配
boolean matches = matcher.matches();
// 查找下一个匹配
boolean found = matcher.find();
// 获取匹配结果
String group = matcher.group(); // 完整匹配
String group1 = matcher.group(1); // 第一个分组
// 获取位置
int start = matcher.start();
int end = matcher.end();
// 替换
String result = matcher.replaceAll("replacement");
分组捕获
// 命名分组
Pattern pattern = Pattern.compile("(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})");
Matcher matcher = pattern.matcher("2024-01-15");
if (matcher.matches()) {
String year = matcher.group("year"); // 2024
String month = matcher.group("month"); // 01
String day = matcher.group("day"); // 15
}
实战示例
1. 手机号验证
public static boolean isValidPhone(String phone) {
return Pattern.matches("^1[3-9]\d{9}$", phone);
}
2. 邮箱验证
public static boolean isValidEmail(String email) {
return Pattern.matches("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$", email);
}
3. 提取数字
public static List<String> extractNumbers(String text) {
List<String> numbers = new ArrayList<>();
Matcher matcher = Pattern.compile("\d+").matcher(text);
while (matcher.find()) {
numbers.add(matcher.group());
}
return numbers;
}
4. 中文验证
public static boolean isChinese(String str) {
return Pattern.matches("^[\u4e00-\u9fa5]+$", str);
}
5. 身份证验证
public static boolean isValidIdCard(String idCard) {
return Pattern.matches("^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$", idCard);
}
性能优化
1. 预编译 Pattern
// 将 Pattern 定义为静态常量
private static final Pattern PHONE_PATTERN = Pattern.compile("^1[3-9]\d{9}$");
2. 避免回溯爆炸
// ❌ 可能导致回溯爆炸
Pattern.compile("^(a+)+$");
// ✅ 使用原子组
Pattern.compile("^(?>a+)+$");
3. 使用非捕获组
// 捕获组
Pattern.compile("(http|https)://.*");
// 非捕获组(性能更好)
Pattern.compile("(?:http|https)://.*");
常用正则模式
// 手机号
private static final Pattern PHONE = Pattern.compile("^1[3-9]\d{9}$");
// 邮箱
private static final Pattern EMAIL = Pattern.compile("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$");
// 身份证
private static final Pattern ID_CARD = Pattern.compile("^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$");
// URL
private static final Pattern URL = Pattern.compile("https?://[^\s]+");
// IP 地址
private static final Pattern IP = Pattern.compile("^((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)$");
总结
Java 的正则表达式功能强大且性能优秀。通过预编译 Pattern、合理使用分组和标志,可以高效地处理字符串匹配和提取任务。