Java 正则表达式 完整详解(语法 + 核心类 + 常用方法 + 实战案例)
目录
一、基础正则语法(通用规则,Java 需转义)
1. 元字符(核心匹配符号)
2. 量词(控制匹配次数)
3. 范围、分组、或逻辑
二、Java 正则核心类 & 两大使用方式
方式 1:便捷字符串内置方法(简单场景)
1. boolean matches(String regex)
2. String[] split(String regex)
3. String replaceAll(String regex, String replacement)
4. String replaceFirst(String regex, String replacement)
方式 2:Pattern + Matcher(复杂场景:查找、分组、多次匹配)
执行流程(固定三步)
1. Pattern 常用静态 / 实例方法
2. Matcher 核心方法(重点)
(1)boolean matches() 全串匹配
(2)boolean find() 查找子串(核心!)
(3)String group() 获取匹配到的内容
(4)start() / end()
三、完整实战代码(分组提取、循环查找)
案例 1:提取所有手机号(11 位数字)
案例 2:分组提取(提取 姓名 + 年龄)
案例 3:过滤特殊字符、清洗文本
四、贪婪匹配 vs 非贪婪匹配(高频踩坑点)
五、常用业务正则模板(直接复制使用)
六、开发最佳实践
Java 正则基于java.util.regex包实现,核心三大类:Pattern(正则模板)、Matcher(匹配器)、PatternSyntaxException(正则语法异常)。
一、基础正则语法(通用规则,Java 需转义)
Java 字符串中反斜杠\是转义符,所以正则里的\必须写成\\。
1. 元字符(核心匹配符号)
| 符号 | 作用 | Java 写法 |
|---|---|---|
. | 匹配任意单个字符(除换行) | . |
\d | 数字 0-9 | \\d |
\D | 非数字 | \\D |
\s | 空白符(空格、制表、换行) | \\s |
\S | 非空白符 | \\S |
\w | 单词字符(字母、数字、下划线) | \\w |
\W | 非单词字符 | \\W |
^ | 行开头 | ^ |
$ | 行结尾 | $ |
2. 量词(控制匹配次数)
| 符号 | 含义 |
|---|---|
X? | X 出现0 次或 1 次(可有可无) |
X* | X 出现0 次、1 次、多次 |
X+ | X 出现至少 1 次 |
X{n} | X 恰好出现n次 |
X{n,} | X 至少n次 |
X{n,m} | X 出现n~m次 |
3. 范围、分组、或逻辑
[abc]:匹配 a/b/c 任意一个[a-z]:小写字母范围;[0-9]数字[^a]:非 a(取反)A|B:匹配 A或B(...):分组,可单独提取分组内容
二、Java 正则核心类 & 两大使用方式
方式 1:便捷字符串内置方法(简单场景)
String类原生封装了正则方法,不用手动创建 Pattern/Matcher,上手最快。
1.boolean matches(String regex)
全串匹配:整个字符串必须完全匹配正则,才返回true。
等价于正则自带
^$首尾限定。
public class RegexDemo { public static void main(String[] args) { // 匹配纯数字(1~多位) String num = "123456"; boolean res1 = num.matches("\\d+"); System.out.println(res1); // true // 带字母,不匹配 String str = "123abc"; boolean res2 = str.matches("\\d+"); System.out.println(res2); // false } }2.String[] split(String regex)
按正则分割字符串,返回数组。
// 按空格/多空格分割 String text = "Java Python Go"; String[] arr = text.split("\\s+"); for (String s : arr) { System.out.println(s); // Java Python Go }3.String replaceAll(String regex, String replacement)
全局替换:匹配所有符合正则的内容并替换。
// 把所有数字替换为 * String content = "手机号:13800138000"; String newStr = content.replaceAll("\\d", "*"); System.out.println(newStr); // 手机号:***********4.String replaceFirst(String regex, String replacement)
只替换第一个匹配项。
方式 2:Pattern + Matcher(复杂场景:查找、分组、多次匹配)
复杂需求(查找子串、提取分组、循环匹配)必须用这两个类,也是工作最常用的写法。
执行流程(固定三步)
Pattern.compile(正则):编译正则模板(建议全局复用,避免重复编译)pattern.matcher(待匹配字符串):创建匹配器Matcher- 调用 Matcher 方法执行匹配、查找、提取
1. Pattern 常用静态 / 实例方法
// 1. 编译正则(静态方法,最常用) Pattern pattern = Pattern.compile("\\d+"); // 2. 简易匹配(等价于 String.matches) boolean match = Pattern.matches("\\d+", "666");2. Matcher 核心方法(重点)
(1)boolean matches()全串匹配
和String.matches功能一致,要求整个字符串完全匹配。
(2)boolean find()查找子串(核心!)
从当前位置向后查找下一个匹配的子串,找到返回true,可循环遍历所有匹配项。
(3)String group()获取匹配到的内容
group():获取整体匹配结果group(int index):获取指定分组(分组从 1 开始,0 代表整体)int groupCount():获取分组总数
(4)start()/end()
start():匹配子串起始下标end():匹配子串结束下标(后一位)
三、完整实战代码(分组提取、循环查找)
案例 1:提取所有手机号(11 位数字)
正则:1[3-9]\\d{9}规则:1 开头,第二位 3-9,后面 9 位数字。
import java.util.regex.Matcher; import java.util.regex.Pattern; public class PhoneRegex { public static void main(String[] args) { String text = "联系我:13812345678,备用:15987654321"; // 1. 编译正则 Pattern p = Pattern.compile("1[3-9]\\d{9}"); // 2. 创建匹配器 Matcher m = p.matcher(text); // 3. 循环查找所有匹配项 while (m.find()) { String phone = m.group(); int start = m.start(); int end = m.end(); System.out.printf("找到手机号:%s,位置:%d ~ %d%n", phone, start, end); } } }输出:
找到手机号:13812345678,位置:5 ~ 16 找到手机号:15987654321,位置:21 ~ 32案例 2:分组提取(提取 姓名 + 年龄)
文本格式:张三(22岁),正则分组:(\\w+)\\((\\d+)岁\\)
- 第 1 组:姓名
(\\w+) - 第 2 组:年龄
(\\d+)
import java.util.regex.Matcher; import java.util.regex.Pattern; public class GroupRegex { public static void main(String[] args) { String str = "李四(25岁)、王五(30岁)"; Pattern p = Pattern.compile("(\\w+)\\((\\d+)岁\\)"); Matcher m = p.matcher(str); while (m.find()) { String name = m.group(1); // 取第一分组 String age = m.group(2); // 取第二分组 System.out.println("姓名:" + name + ",年龄:" + age); } } }案例 3:过滤特殊字符、清洗文本
public class CleanText { public static void main(String[] args) { String raw = "Hello!@#$ Java 123_"; // 保留字母、数字、下划线,其余替换为空 String res = raw.replaceAll("[^a-zA-Z0-9_]", ""); System.out.println(res); // HelloJava123_ } }四、贪婪匹配 vs 非贪婪匹配(高频踩坑点)
Java 正则默认贪婪:尽可能匹配最长内容。 在量词后加?变为非贪婪(最短匹配)。
| 类型 | 写法 | 特点 |
|---|---|---|
| 贪婪 | .* | 匹配到最后 |
| 非贪婪 | .*? | 匹配到最近的结束符 |
示例:提取<>内内容
String html = "<div>内容1</div><div>内容2</div>"; // 1. 贪婪匹配 .* (错误,一次性匹配整串) Pattern p1 = Pattern.compile("<div>(.*)</div>"); Matcher m1 = p1.matcher(html); if(m1.find()){ System.out.println("贪婪:" + m1.group(1)); // 内容1</div><div>内容2 } // 2. 非贪婪 .*? (正确,逐个匹配) Pattern p2 = Pattern.compile("<div>(.*?)</div>"); Matcher m2 = p2.matcher(html); while(m2.find()){ System.out.println("非贪婪:" + m2.group(1)); }五、常用业务正则模板(直接复制使用)
- 纯数字:
\\d+ - 非空字符串(不含空白):
\\S+ - 邮箱:
\\w+@\\w+\\.\\w+(\\.\\w+)? - 11 位手机号:
1[3-9]\\d{9} - 去除所有空格:
\\s+ - 中文字符:
[\\u4e00-\\u9fa5]
六、开发最佳实践
- Pattern 尽量全局单例
Pattern.compile()编译开销大,不要在循环 / 方法内频繁创建。 - 简单替换 / 分割 → 用
String自带方法;查找、分组→ 必用Pattern+Matcher。 - 正则中
. * + ? ( ) [ ] \都是特殊字符,如需原样匹配,用\\转义。 - 复杂正则先在线正则工具测试,再写入 Java 代码。
