Java 正则表达式

Java 正则表达式

1. 概述

正则表达式(Regular Expression,简称 regex)是一种用于匹配字符串的模式描述语言。在 Java 中,正则表达式通过 java.util.regex 包提供支持,主要包括以下三个核心类:

  • Pattern:表示编译后的正则表达式。
  • Matcher:用于对输入字符串执行匹配操作。
  • PatternSyntaxException:当正则表达式语法错误时抛出的异常。

Java 的正则表达式遵循 Perl 5 兼容的语法规范,功能强大且灵活,适用于文本验证、提取、替换和分割等场景。


2. 基本使用流程

2.1 编译正则表达式

java 复制代码
Pattern pattern = Pattern.compile("your-regex");

注意Pattern 对象是线程安全且不可变的,可被多个线程共享以提高性能。

2.2 创建匹配器

java 复制代码
Matcher matcher = pattern.matcher("input string");

2.3 执行匹配操作

常用方法包括:

方法 描述
matches() 判断整个字符串是否匹配正则表达式
find() 查找下一个匹配子串(可用于多次调用)
lookingAt() 判断字符串开头是否匹配
replaceAll(String replacement) 替换所有匹配项
replaceFirst(String replacement) 替换第一个匹配项
group(int group) 获取指定捕获组的内容

3. 正则表达式语法详解

3.1 字符类

表达式 含义
[abc] 匹配 a、b 或 c
[^abc] 不匹配 a、b、c
[a-z] 匹配小写字母 a 到 z
[0-9] 等价于 \d
\w 单词字符(等价于 [a-zA-Z_0-9]
\W 非单词字符
\s 空白字符(空格、制表符、换行等)
\S 非空白字符
\d 数字(等价于 [0-9]
\D 非数字

3.2 量词(Quantifiers)

表达式 含义
X? X 出现 0 次或 1 次(贪婪)
X* X 出现 0 次或多次
X+ X 出现 1 次或多次
X{n} X 恰好出现 n 次
X{n,} X 至少出现 n 次
X{n,m} X 出现 n 到 m 次

贪婪 vs 惰性 :默认为贪婪匹配。在量词后加 ? 可变为惰性(如 .*?)。

3.3 边界匹配器

表达式 含义
^ 行的开始
$ 行的结束
\b 单词边界
\B 非单词边界
\A 输入的开始
\Z 输入的结束(忽略最后的换行符)
\z 输入的绝对结束

3.4 分组与捕获

使用圆括号 () 创建捕获组:

java 复制代码
Pattern p = Pattern.compile("(\\d{4})-(\\d{2})-(\\d{2})");
Matcher m = p.matcher("2026-01-22");
if (m.matches()) {
    System.out.println(m.group(1)); // "2026"
    System.out.println(m.group(2)); // "01"
    System.out.println(m.group(3)); // "22"
}
  • group(0):整个匹配内容。
  • group(n):第 n 个捕获组(从 1 开始计数)。
  • 非捕获组:使用 (?:...),例如 (?:\d{3}) 不保存匹配结果。

3.5 零宽断言(Lookaround)

表达式 含义
(?=X) 正向先行断言(后面必须是 X)
(?!X) 负向先行断言(后面不能是 X)
(?<=X) 正向后行断言(前面必须是 X)
(?<!X) 负向后行断言(前面不能是 X)

注意 :Java 支持固定长度的后行断言(如 (?<=abc)),但不支持可变长度(如 (?<=a+))。


4. 常用示例

4.1 验证邮箱

java 复制代码
String emailRegex = "^[a-zA-Z0-9_+&*-]+(?:\\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,7}$";
boolean isValid = email.matches(emailRegex);

4.2 提取所有数字

java 复制代码
Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("Price: $123 and ID: 4567");
while (m.find()) {
    System.out.println(m.group()); // 输出 123, 4567
}

4.3 替换敏感词

java 复制代码
String text = "This is a bad word.";
String result = text.replaceAll("(bad|ugly)", "***");
// 结果: "This is a *** word."

4.4 分割字符串(保留分隔符)

java 复制代码
String[] parts = "a,b;c".split("[,;]");
// ["a", "b", "c"]

5. 性能优化建议

  1. 预编译 Pattern :避免在循环中重复调用 Pattern.compile()

    java 复制代码
    private static final Pattern EMAIL_PATTERN = 
        Pattern.compile("^[\\w.-]+@[\\w.-]+\\.[a-zA-Z]{2,}$");
  2. 避免回溯爆炸 :谨慎使用嵌套量词(如 (a+)+),可能导致指数级回溯。

  3. 使用 String.matches() 谨慎 :该方法隐式添加了 ^...$,仅适用于全字符串匹配。

  4. 考虑使用 java.util.function.Predicate 封装验证逻辑

    java 复制代码
    Predicate<String> isEmail = EMAIL_PATTERN.asPredicate();

6. 异常处理

正则表达式语法错误会抛出 PatternSyntaxException

java 复制代码
try {
    Pattern.compile("[");
} catch (PatternSyntaxException e) {
    System.err.println("Invalid regex: " + e.getDescription());
}

7. 与其他工具对比

特性 Java Regex JavaScript Python (re)
Unicode 支持 完整(UTF-16) 有限 完整
后行断言 固定长度 ES2018+ 支持 支持(固定/可变)
命名捕获组 Java 7+ 支持 (?<name>...) ES2018+ 支持
多行模式 Pattern.MULTILINE /m 标志 re.MULTILINE

8. 高级特性(Java 7+)

8.1 呓名捕获组

java 复制代码
Pattern p = Pattern.compile("(?<year>\\d{4})-(?<month>\\d{2})");
Matcher m = p.matcher("2026-01");
if (m.matches()) {
    System.out.println(m.group("year"));  // "2026"
    System.out.println(m.group("month")); // "01"
}

8.2 标志(Flags)

可通过 Pattern.compile(regex, flags) 设置:

标志 作用
Pattern.CASE_INSENSITIVE 忽略大小写
Pattern.MULTILINE ^$ 匹配每行
Pattern.DOTALL . 匹配包括换行符
Pattern.UNICODE_CASE CASE_INSENSITIVE 联用支持 Unicode

也可在正则内部使用内联标志:(?i) 表示忽略大小写。


9. 总结

Java 正则表达式是处理字符串的强大工具,适用于验证、解析、清洗等多种场景。合理使用 PatternMatcher 类,结合对正则语法的深入理解,可以高效解决复杂的文本处理问题。同时需注意性能陷阱和安全性(如 ReDoS 攻击),在生产环境中应进行充分测试。


参考文献

相关推荐
仰泳之鹅1 小时前
【杂谈】C语言中的链接属性、声明周期以及static关键字
java·c语言·前端
空空kkk1 小时前
Spring Boot项目的搭建
java·spring boot·后端
2501_940315261 小时前
【无标题】(leetcode933)最近的请求次数
java·前端·javascript
Sheep Shaun1 小时前
深入理解红黑树:从概念到完整C++实现详解
java·开发语言·数据结构·c++·b树·算法
每天学习一丢丢1 小时前
Spring Boot 调用泛微 E9 Token 认证 + 创建流程完整教程
java·spring boot·后端
苦逼的老王2 小时前
《java-使用kkview+libreoffice 实现在线预览ppt、xls、doc、pdf..》
java·pdf·powerpoint
没有bug.的程序员2 小时前
Spring Boot 启动原理:从 @SpringBootApplication 到自动配置深度解析
java·spring boot·后端·python·springboot·application
jiaguangqingpanda2 小时前
Day26-20260122
java·算法·排序算法
Ahtacca2 小时前
拒绝重复造轮子:利用自定义注解封装POI,实现Java通用Excel解析
java·javascript·vue·excel