目录
[一、基础正则语法(通用规则,Java 需转义)](#一、基础正则语法(通用规则,Java 需转义))
[1. 元字符(核心匹配符号)](#1. 元字符(核心匹配符号))
[2. 量词(控制匹配次数)](#2. 量词(控制匹配次数))
[3. 范围、分组、或逻辑](#3. 范围、分组、或逻辑)
[二、Java 正则核心类 & 两大使用方式](#二、Java 正则核心类 & 两大使用方式)
[方式 1:便捷字符串内置方法(简单场景)](#方式 1:便捷字符串内置方法(简单场景))
[1. boolean matches(String regex)](#1. boolean matches(String regex))
[2. String\[\] split(String regex)](#2. String[] split(String regex))
[3. String replaceAll(String regex, String replacement)](#3. String replaceAll(String regex, String replacement))
[4. String replaceFirst(String regex, String replacement)](#4. String replaceFirst(String regex, String replacement))
[方式 2:Pattern + Matcher(复杂场景:查找、分组、多次匹配)](#方式 2:Pattern + Matcher(复杂场景:查找、分组、多次匹配))
[1. Pattern 常用静态 / 实例方法](#1. Pattern 常用静态 / 实例方法)
[2. Matcher 核心方法(重点)](#2. Matcher 核心方法(重点))
[(1)boolean matches() 全串匹配](#(1)boolean matches() 全串匹配)
[(2)boolean find() 查找子串(核心!)](#(2)boolean find() 查找子串(核心!))
[(3)String group() 获取匹配到的内容](#(3)String group() 获取匹配到的内容)
[(4)start() / end()](#(4)start() / end())
[案例 1:提取所有手机号(11 位数字)](#案例 1:提取所有手机号(11 位数字))
[案例 2:分组提取(提取 姓名 + 年龄)](#案例 2:分组提取(提取 姓名 + 年龄))
[案例 3:过滤特殊字符、清洗文本](#案例 3:过滤特殊字符、清洗文本)
[四、贪婪匹配 vs 非贪婪匹配(高频踩坑点)](#四、贪婪匹配 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 代码。