一、什么是正则表达式?
正则表达式(Regular Expression)是一种文本模式,用于描述、匹配、搜索或替换符合某种规则的字符串。其在日志提取、表单校验、配置清洗、数据爬取等场景中被广泛使用。
Java 提供了完整的正则表达式支持,核心类如下:
-
java.util.regex.Pattern
:编译正则表达式 -
java.util.regex.Matcher
:对文本进行匹配、提取 -
String.matches()
/replaceAll()
/split()
等方法:简化使用
示例代码:
Pattern pattern = Pattern.compile("\\d{4}-\\d{2}-\\d{2}");
Matcher matcher = pattern.matcher("2025-07-10");
if (matcher.matches()) {
System.out.println("匹配成功");
}
二、正则表达式语法概览(核心语法)
语法 | 含义 | 示例 | 说明 |
---|---|---|---|
. |
任意字符(除换行) | a.c |
可匹配 abc , a9c 等 |
^ |
开始 | ^abc |
必须以 abc 开头 |
$ |
结束 | xyz$ |
必须以 xyz 结尾 |
* |
0 次或多次 | a* |
可匹配 "" , a , aaaa |
+ |
1 次或多次 | a+ |
不匹配空串 |
? |
0 次或 1 次 | a? |
匹配 0 或 1 次 a |
{n} |
恰好 n 次 | a{3} |
匹配 aaa |
{n,} |
至少 n 次 | a{2,} |
至少两个 a |
{n,m} |
n~m 次 | a{2,4} |
2 到 4 个 a |
[] |
字符类 | [abc] |
匹配 a、b、c 中任意一个 |
[^] |
排除字符类 | [^abc] |
不匹配 a/b/c |
` | ` | 或 | `cat |
() |
分组 | (abc)+ |
分组重复匹配 |
\d |
数字 | \d+ |
等价于 [0-9]+ |
\w |
单词字符 | [a-zA-Z0-9_] |
|
\s |
空白字符 | 包括空格、换行、制表符 |
三、Java 使用建议(工程实践)
1. 推荐写法:Pattern + Matcher
Pattern pattern = Pattern.compile("^[a-zA-Z0-9_-]{4,16}$");
Matcher matcher = pattern.matcher("user_1234");
if (matcher.matches()) {
// 合法用户名
}
2. 避免错误写法
// 错误:正则表达式字符串忘记转义
Pattern.compile("\d{3}"); // 实际匹配的是"d{3}",不是数字
应写为:
Pattern.compile("\\d{3}");
四、正则表达式学习路径
第一阶段:语法基础
- 学习字符类(
[abc]
、\d
)、量词(*
、+
、?
)、边界(^
、$
)
第二阶段:复杂匹配
- 分组与捕获、非贪婪匹配、断言(正向 / 负向)
第三阶段:调试与性能
-
使用
Matcher
提取组信息、使用预编译Pattern
避免重复编译 -
注意回溯型表达式造成的性能问题(避免
(a+)+
)
五、常见场景与对应正则表达式
1. 表单验证(校验用户输入)
场景 | 正则表达式 | 说明 |
---|---|---|
用户名(4-16位) | ^[a-zA-Z0-9_-]{4,16}$ |
字母数字下划线 |
中文名 | ^[\u4e00-\u9fa5]{2,10}$ |
只支持中文 |
邮箱 | ^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$ |
常见邮箱格式 |
手机号(中国) | ^1[3-9]\d{9}$ |
三大运营商 |
身份证(中国18位) | `^\d{6}(18 | 19 |
密码强度(数字+字母) | ^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{6,}$ |
至少一个字母和数字 |
2. 网络相关
场景 | 正则表达式 |
---|---|
IPv4 | `^((25[0-5] |
URL | `^(http |
域名 | ^([a-zA-Z0-9]+(-[a-zA-Z0-9]+)*\.)+[a-zA-Z]{2,}$ |
3. 时间与日期
场景 | 正则表达式 |
---|---|
日期(yyyy-MM-dd) | ^\d{4}-\d{2}-\d{2}$ |
时间(HH:mm:ss) | `^([01]\d |
年月日时间戳 | ^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$ |
4. 日志抽取与数据清洗
场景 | 正则表达式 | 提示 |
---|---|---|
提取日志级别 | `\b(INFO | DEBUG |
提取 JSON 键值对 | "(\w+)":\s*"([^"]+)" |
适合简单 JSON |
去除 HTML 标签 | <[^>]+> |
清洗富文本 |
去除空白字符 | \s+ |
用于压缩字符串 |
清除特殊字符 | [^a-zA-Z0-9\u4e00-\u9fa5] |
保留中英文与数字 |
六、常见问题与性能陷阱
⚠️ 正则性能陷阱
-
(a+)+
会造成回溯爆炸,处理大文本时极其慢; -
避免重复编译:将
Pattern
定义为静态成员或缓存; -
替换时,尽量使用非捕获组
(?:...)
避免组开销; -
编写复杂表达式时推荐加注释(Java 8+ 支持
(?x)
模式):Pattern.compile("(?x) # 启用注释模式
\d{4} # 年份
- # 分隔符
\d{2} # 月份
- # 日
");
七、构建正则表达式库(正则标准化)
建议为团队或项目构建统一正则工具类,方便调用与维护:
public class RegexLib {
public static final String EMAIL = "^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$";
public static final String PHONE = "^1[3-9]\\d{9}$";
public static final String ID_CARD = "^\\d{17}[\\dXx]$";
public static final String DATE = "^\\d{4}-\\d{2}-\\d{2}$";
public static boolean match(String pattern, String input) {
return Pattern.matches(pattern, input);
}
}
使用:
if (RegexLib.match(RegexLib.EMAIL, "user@test.com")) {
// 合法邮箱
}
八、总结:正则表达式在工程中的地位
在中大型项目中,正则表达式应作为工具语言中的基础技能 被系统掌握。学习正则不仅是掌握语法,更要理解其行为模型与性能特性,避免常见陷阱,构建可复用的正则库。