前言准备知识
常用元字符及其含义
| 元字符 | 含义 | 示例 | 匹配结果 |
|---|---|---|---|
. |
匹配除换行符外的任意单个字符 | a.c |
匹配"abc"、"a c"、"a#c"等 |
^ |
匹配字符串的开始位置 | ^Hello |
匹配以"Hello"开头的字符串 |
$ |
匹配字符串的结束位置 | world$ |
匹配以"world"结尾的字符串 |
* |
匹配前一个字符0次或多次 | ab*c |
匹配"ac"、"abc"、"abbc"等 |
+ |
匹配前一个字符1次或多次 | ab+c |
匹配"abc"、"abbc",不匹配"ac" |
? |
匹配前一个字符0次或1次 | colou?r |
匹配"color"和"colour" |
{n} |
匹配前一个字符恰好n次 | a{3} |
匹配"aaa" |
{n,} |
匹配前一个字符至少n次 | a{2,} |
匹配"aa"、"aaa"等 |
{n,m} |
匹配前一个字符n到m次 | a{2,4} |
匹配"aa"、"aaa"、"aaaa" |
一、Java正则表达式基础语法
1.1 元字符体系
元字符是构成正则表达式的核心要素,Java支持的标准元字符包括:
java
// 字符类元字符
String digitPattern = "\\d"; // 匹配数字 [0-9]
String wordPattern = "\\w"; // 匹配单词字符 [a-zA-Z0-9_]
String spacePattern = "\\s"; // 匹配空白字符 [ \t\n\x0B\f\r]
String nonDigitPattern = "\\D"; // 匹配非数字
String nonWordPattern = "\\W"; // 匹配非单词字符
String nonSpacePattern = "\\S"; // 匹配非空白字符
// 边界匹配元字符
String startPattern = "^\\d+"; // 匹配以数字开头的字符串
String endPattern = "\\w+$"; // 匹配以单词字符结尾的字符串
String wordBoundary = "\\bjava\\b"; // 匹配完整单词"java"
1.2 量词运算符
量词控制模式重复次数,是构建复杂匹配规则的关键:
java
// 贪婪量词(默认)
String greedy = "a*"; // 匹配0个或多个a(尽可能多)
String reluctant = "a*?"; // 匹配0个或多个a(尽可能少)
String possessive = "a*+"; // 匹配0个或多个a(独占模式)
// 具体次数限定
String exact = "a{3}"; // 精确匹配3个a
String range = "a{2,4}"; // 匹配2到4个a
String atLeast = "a{2,}"; // 匹配至少2个a
二、常用正则表达式模式库
2.1 数据验证类模式
| 验证类型 | 正则表达式 | 应用场景 |
|---|---|---|
| 邮箱验证 | ^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$ |
用户注册、登录验证 |
| 手机号码 | ^1[3-9]\\d{9}$ |
中国大陆手机号验证 |
| 身份证号 | `^[1](#验证类型 正则表达式 应用场景 邮箱验证 ^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,} 用户注册、登录验证 手机号码 ^1[3-9]\\d{9} 中国大陆手机号验证 身份证号 1\d{5}(18 19 IP地址 ^((25[0-5] 2[0-4]\d)^\d{5}(18 |
19 |
| IP地址 | `^((25[0-5] | 2[0-4]\d |
邮箱正则表达式解析:
^[a-zA-Z0-9._%+-]+:匹配邮箱用户名部分,包含字母、数字和特定符号@:匹配@符号[a-zA-Z0-9.-]+:匹配域名部分\.[a-zA-Z]{2,}$:匹配顶级域名,至少2个字母
2.2 文本处理类模式
java
// URL提取
String urlPattern = "https?://[\\w./?=&%-]+";
String text = "访问https://www.example.com/page?param=value获取详情";
Pattern.compile(urlPattern).matcher(text).results()
.forEach(match -> System.out.println("发现URL: " + match.group()));
// HTML标签移除
String htmlPattern = "<[^>]+>";
String htmlText = "<div>Hello <b>World</b></div>";
String plainText = htmlText.replaceAll(htmlPattern, "");
System.out.println("纯文本: " + plainText); // 输出: Hello World
// 中文提取
String chinesePattern = "[\\u4e00-\\u9fa5]+";
String mixedText = "Hello你好World世界";
Pattern.compile(chinesePattern).matcher(mixedText).results()
.forEach(match -> System.out.println("中文: " + match.group()));
三、Java正则API深度解析
3.1 Pattern与Matcher协同工作流
java
public class RegexAdvancedExample {
public static void main(String[] args) {
String text = "订单号: ORD20231215001, 金额: ¥1,250.50, 日期: 2023-12-15";
// 复合模式匹配
String orderPattern = "ORD(\\d{8})(\\d{3})";
String amountPattern = "¥([\\d,]+)\\.(\\d{2})";
String datePattern = "(\\d{4})-(\\d{2})-(\\d{2})";
// 订单号解析
Matcher orderMatcher = Pattern.compile(orderPattern).matcher(text);
if (orderMatcher.find()) {
String orderDate = orderMatcher.group(1); // 20231215
String sequence = orderMatcher.group(2); // 001
System.out.printf("订单日期: %s, 序列号: %s%n", orderDate, sequence);
}
// 金额解析与转换
Matcher amountMatcher = Pattern.compile(amountPattern).matcher(text);
if (amountMatcher.find()) {
String integerPart = amountMatcher.group(1).replace(",", "");
String decimalPart = amountMatcher.group(2);
double amount = Double.parseDouble(integerPart + "." + decimalPart);
System.out.printf("解析金额: %.2f%n", amount);
}
}
}
3.2 分组与反向引用
分组机制允许对匹配的子表达式进行单独操作和引用:
java
public class GroupReferenceExample {
public static void main(String[] args) {
// 重复单词检测
String duplicatePattern = "\\b(\\w+)\\b\\s+\\1\\b";
String text = "这是一个测试测试文本,包含重复重复的词语";
Matcher matcher = Pattern.compile(duplicatePattern).matcher(text);
while (matcher.find()) {
System.out.println("发现重复: " + matcher.group(1));
}
// 日期格式重组
String dateText = "2023/12/15";
String rearranged = dateText.replaceAll("(\\d{4})/(\\d{2})/(\\d{2})", "$1年$2月$3日");
System.out.println("格式转换: " + rearranged); // 2023年12月15日
}
}
四、性能优化与最佳实践
4.1 Pattern预编译策略
对于频繁使用的正则表达式,预编译能显著提升性能:
java
public class OptimizedRegex {
// 预编译常用模式
private static final Pattern EMAIL_PATTERN =
Pattern.compile("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$");
private static final Pattern PHONE_PATTERN =
Pattern.compile("^1[3-9]\\d{9}$");
private static final Pattern URL_PATTERN =
Pattern.compile("https?://[\\w./?=&%-]+");
public boolean validateEmail(String email) {
return EMAIL_PATTERN.matcher(email).matches();
}
public boolean validatePhone(String phone) {
return PHONE_PATTERN.matcher(phone).matches();
}
public List<String> extractUrls(String text) {
return URL_PATTERN.matcher(text).results()
.map(MatchResult::group)
.collect(Collectors.toList());
}
}
4.2 复杂文本解析实战
java
public class LogParser {
private static final Pattern LOG_PATTERN = Pattern.compile(
"^(\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}:\\d{2})\\s+" +
"(\\w+)\\s+" +
"\\[(\\w+)\\]\\s+" +
"(.*?)\\s+" +
"-\\s+(.+)$"
);
public void parseLogEntry(String logLine) {
Matcher matcher = LOG_PATTERN.matcher(logLine);
if (matcher.matches()) {
String timestamp = matcher.group(1);
String level = matcher.group(2);
String thread = matcher.group(3);
String logger = matcher.group(4);
String message = matcher.group(5);
System.out.printf("时间: %s, 级别: %s, 线程: %s, 记录器: %s, 消息: %s%n",
timestamp, level, thread, logger, message);
}
}
}
- 1-9 ↩︎