Java 里面正则表达式匹配字符串,核心是依靠 java.util.regex 包下面的 Pattern 和 Matcher 两个类,String 类本身也内置 matches 方法可以做简易全匹配,正则本质就是一套特殊规则字符串,用来描述字符的排列规律,实现校验提取替换查找,比如校验手机号邮箱身份证,从长文本里面抽取指定内容,很多新手会混淆全匹配和部分匹配,matches 方法要求整个字符串完全符合正则规则才算匹配成功,如果只是文本里面局部包含符合规则的片段,就必须使用 Matcher 的 find 方法,Java 正则底层是 NFA 非确定有限自动机,编写正则的时候要特别注意贪婪匹配回溯问题,复杂正则容易出现性能下降,学习的时候要掌握元字符量词分组捕获边界这些基础语法,再结合 Pattern Matcher 完整 API,就能熟练完成各类字符串匹配业务需求。
一 核心类与基础 API
1 Pattern 类
Pattern 代表编译之后的正则表达式对象,正则字符串不能每次匹配都重复解析,推荐先用 Pattern.compile 编译正则,编译之后复用,性能比直接调用 String.matches 更好,还可以传入标志位,比如忽略大小写多行模式。
2 Matcher 类
Matcher 是匹配器,绑定正则和待匹配字符串,提供多个匹配相关方法,find 查找下一个匹配片段,lookingAt 从字符串开头尝试匹配,matches 全字符串匹配,group 获取捕获分组内容,start end 获取匹配位置。
3 String 内置 matches 方法
写法最简单,底层内部仍然是调用 Pattern 和 Matcher,只适合一次性简单校验,缺点是每次调用都会重新编译正则,循环大量数据的时候性能差,不推荐高频场景使用。
二 正则基础元字符与语法清单
1 基础元字符
. 匹配除换行之外任意单个字符
d 匹配数字 等价 0 到 9
w 匹配字母数字下划线
s 匹配空白字符 空格制表符换行
^ 匹配字符串开头
$ 匹配字符串结尾
2 量词
- 前面元素出现零次或者多次
- 前面元素出现一次或者多次
? 前面元素出现零次或者一次
{n} 固定 n 次
{n,} 至少 n 次
{n,m} n 到 m 次
3 分组与捕获
小括号代表分组,分组会捕获匹配内容,group1 group2 可以取出分组结果,非捕获分组可以取消捕获,减少内存开销。
4 贪婪 懒惰 独占匹配
贪婪匹配默认尽可能多匹配,加问号变成懒惰匹配,尽可能少匹配,独占匹配不回溯,性能更高但是容错低,这个是 Java 正则匹配字符串最容易踩坑的知识点。
三 常见代码写法
第一种 全匹配校验
使用 matches 或者 Pattern.matches,判断整串是否符合规则,典型场景邮箱手机号格式校验。
第二种 局部查找匹配
Pattern 编译正则,创建 Matcher 对象,循环调用 find,通过 group 取出每一处匹配内容,适合从大段文本抽取多个目标字符串。
第三种 替换匹配内容
Matcher 的 replaceAll replaceFirst,按照正则匹配到的片段做替换,常用于清洗文本。
四 常用标志位表格
| 标志常量 | 作用 | 适用场景 |
|---|---|---|
| Pattern.CASE_INSENSITIVE | 忽略大小写匹配 | 邮箱网址不区分大小写校验 |
| Pattern.MULTILINE | 多行模式 ^ $ 识别每行首尾 | 多行日志文本处理 |
| Pattern.DOTALL | 点号可以匹配换行符 | 跨多行文本匹配 |
| Pattern.COMMENTS | 正则里面允许注释和空格 | 复杂正则提升可读性 |
五 实操学习步骤
第一步先掌握元字符量词分组基础语法,单独写简单正则测试数字字母组合匹配。
第二步区分 matches 全匹配和 find 局部匹配,写 demo 对比两者执行结果,理解两者核心差别。
第三步学习分组捕获,练习提取括号里面的内容,理解 group0 代表整体匹配,group1 开始是子分组。
第四步研究贪婪匹配回溯问题,测试长文本下正则性能,学习懒惰匹配写法优化。
第五步在业务场景练习,比如日志提取手机号身份证,文本清洗替换,熟悉 Pattern 编译复用优化方式。
总结,java 正则表达式匹配字符串,核心工具就是 Pattern Matcher,String.matches 只是简易封装,重点区分全匹配局部查找,理解元字符量词分组贪婪匹配,写正则的时候尽量避免过度复杂嵌套,防止回溯造成性能问题,高频匹配场景一定要提前编译 Pattern 复用,不要重复编译正则表达式。
【常见问题】
问题 1 java 正则表达式匹配字符串,matches 和 find 有什么区别
回答 1 java 正则表达式匹配字符串里面,matches 要求整个待匹配字符串全部符合正则规则,属于全匹配,find 是在字符串内部查找下一处符合正则的片段,属于局部匹配,长文本提取内容一般使用 find。
问题 2 java 正则表达式匹配字符串,为什么循环大量数据推荐 Pattern.compile
回答 2 java 正则表达式匹配字符串里面,每次调用 String.matches 都会重新编译正则表达式,大量循环场景重复编译开销很大,Pattern.compile 提前编译正则对象之后复用 Matcher,大幅提升匹配性能。
问题 3 java 正则表达式匹配字符串,贪婪匹配是什么意思
回答 3 java 正则表达式匹配字符串里面,贪婪匹配是默认行为,正则会尽可能多的匹配字符,容易触发回溯,在量词后面加问号可以改成懒惰匹配,尽可能少匹配,适合精准截取文本。
问题 4 java 正则表达式匹配字符串,group0 代表什么内容
回答 4 java 正则表达式匹配字符串里面,group0 代表正则整体匹配到的完整字符串,group1 group2 对应小括号分组依次捕获的子内容,没有分组的时候调用 group1 会抛出异常。
【免责申明】
本文内容基于 JDK 标准 java.util.regex 包语法整理,不同 JDK 版本正则引擎行为基本一致,但是极端复杂正则回溯性能存在差异,本文仅作为学习参考,生产环境高并发场景需要额外做正则性能压测,不代表所有业务场景都可以直接套用。
