正则表达式
来源
- 触发点:由 ObsidianToAnki 制卡插件带来的疑惑,学习正则表达式相关知识,记录成文
- 首次记录:2024-08-16
- 作者:huan
洞见
“正则是精确描述文本结构的语言。”
写好正则的关键不在于记住所有符号,而在于清晰定义业务规则边界;避免“试错式”编写,先用自然语言描述需求,再转化为模式。
详情
核心概念
| 符号 | 含义 | 示例 |
|---|
^ | 字符串开头 | ^abc → 以 abc 开头 |
$ | 字符串结尾 | xyz$ → 以 xyz 结尾 |
. | 任意字符 | .{6,} → 任意字符,至少出现 6 次 |
* | 0 次或多次 | ab*c → ac, abc, abbc… |
+ | 1 次或多次 | a+ → a, aa, aaa… |
? | 0 或 1 次 | colou?r → color / colour |
\d | 数字(等价 [0-9]) | \d{3} → 三位数字 |
\w | 字母、数字、下划线 | \w+ → 有效标识符 |
{n,m} | 重复 n 到 m 次 | \d{2,4} → 2~4 位数字 |
[] | 字符集合 | [aeiou] → 任意元音字母 |
() | 分组捕获 | (ab)+ → ab, abab… |
(?=...) | 正向先行断言(零宽) | (?=\d) → 后面必须有数字,但不消耗 |
元字符分类
| 类别 | 符号 | 说明 |
|---|
| 锚点 | ^, $, \b | 匹配位置而非字符 |
| 量词 | *, +, ?, {n,m} | 控制重复次数 |
| 字符类 | \d, \w, \s, [...] | 匹配一类字符 |
| 分组 | (...), (?:...) | 捕获或非捕获分组 |
| 断言 | (?=...), (?!...) | 条件判断,不消耗字符 |
⚠️ Java 字符串中需转义反斜杠:\d → "\\d"
实际案例
手机号
// 手机号
String mobile = "^1[3-9]\\d{9}$";
| 组成 | 含义 |
|---|
^ | 字符串开头 |
1 | 第一位必须是 1 |
[3-9] | 第二位是 3 到 9 的数字 |
\d{9} | 后续 9 位都是数字 |
$ | 字符串结尾 |
密码校验
// 密码校验:至少6位,含大小写字母、数字、特殊字符
String strongPwd = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[!@#$%^&*]).{6,}$";
| 组成 | 含义 |
|---|
^ | 表示字符串的开始 |
.* | 表示“允许跳过任意字符”,.不可省略,否则断言只能检查开头 |
(?=.*[a-z]) | 肯定先行断言:确保字符串中包含至少一个小写字母 |
(?=.*[A-Z]) | 肯定先行断言:确保字符串中包含至少一个大写字母 |
(?=.*\\d) | 肯定先行断言:确保字符串中包含至少一个数字(\d 等价于 [0-9]) |
(?=.*[!@#$%^&*]) | 肯定先行断言:确保字符串中包含至少一个特殊字符(限定为 !@#$%^&* 中的任意一个) |
.{6,} | 匹配任意字符(除换行符外),至少 6 个;,不可省略,否则表示“恰好 6 位” |
$ | 表示字符串的结束 |
非纯字母
// 不能是纯字母(允许纯数字或混合)
String notPureLetter = "^[a-zA-Z0-9]*\\d[a-zA-Z0-9]*$";
| 组成 | 含义 |
|---|
^ | 表示字符串的开始,确保从第一个字符开始匹配 |
[a-zA-Z0-9]* | 匹配 0 个或多个字母(大小写)或数字(即“字母数字字符”),允许开头没有数字 |
\\d(实际为 \d) | 匹配恰好一个数字(等价于 [0-9]),这是整个字符串中必须存在的数字 |
[a-zA-Z0-9]* | 再次匹配 0 个或多个字母或数字,允许数字后面还有字母或数字 |
$ | 表示字符串的结束,确保整个字符串都被匹配,不能包含其他字符(如空格、特殊符号等) |
预设使用场景
- 表单校验:用户名、密码、手机号、邮箱、身份证号
- 数据清洗:去除非法字符、标准化格式
- 日志解析:提取时间戳、IP、错误码
- 文本替换:批量修改配置文件、模板变量
我的想法
潜在问题
- 可读性差:复杂正则理解困难,需配合注释或拆分为多步校验。
- 性能风险:回溯爆炸(如
(a+)+b 匹配 aaaaaaaaa!)可导致 CPU 占满。
- 平台差异:Java 不支持
\p{L}(Unicode 字母)以外的部分 Unicode 属性,需查文档。
- 安全漏洞:用户输入直接拼接正则可能引发 ReDoS(正则拒绝服务)。
优化拓展
- 分步校验:将复杂规则拆为多个简单正则 + 逻辑判断(如先长度,再字符组成)。
- 预编译 Pattern:高频调用场景下缓存
Pattern.compile() 实例,避免重复解析。
- 结合工具库:
- 邮箱/URL 校验 → Apache Commons Validator
- 国际化手机号 → Google libphonenumber
关联网络
演化日志
- v0.1 (2024-08-16):记录为待学习内容
- v0.2 (2025-10-31):完成初始版本
- v0.3 (2025-11-26):补充关联网络、演化日志、附件参考、待办事项
复习回顾
📈 轮次: 1 🕒 lastReview: 2025-11-26 11:46:38 📅 nextReview: 2025-12-03 00:00:00
附件参考
待办事项