regular-expression
正则表达式基础
NOTE
正则的所有规则,都可以归为两类:「匹配什么字符」 和 「匹配多少个」
1.匹配「单个字符」的核心符号
| 符号 | 大白话解释 | 极简例子(测试文本:abc123ABC_@ 换行) | 匹配结果 |
|---|---|---|---|
| 普通字符 | 匹配和自身完全一模一样的字符 | a | 匹配文本里的a |
.(点号) | 匹配除换行符\n外的任意单个字符(万能牌) | a.c | 匹配abc、a1c,不匹配a\nc |
[](字符集) | 匹配括号内的任意 1 个字符(多选一),支持范围写法 | [abc]、[0-9]、[a-z] | 前者匹配a/b/c,中者匹配任意数字,后者匹配任意小写字母 |
[^](排除字符集) | 匹配除了括号内的任意 1 个字符 | [^0-9] | 匹配所有非数字的字符 |
\d | 匹配任意 1 个数字,等价于[0-9](超高频) | \d | 匹配1/2/3 |
\w | 匹配任意 1 个字母、数字、下划线_,等价于[a-zA-Z0-9_] | \w | 匹配a/b/c/1/2/3/_,不匹配@/空格 |
\s | 匹配任意 1 个空白字符(空格、Tab 制表符、换行符\n) | \s | 匹配文本里的空格、换行 |
\D/\W/\S | 对应上面三个的反义:非数字、非字母数字下划线、非空白 | \D | 匹配所有不是数字的字符 |
WARNING
- 解决「要找什么字 / 内容」的问题,每个符号只匹配1 个字符
^有两个完全不同的含义!在[]里面是「排除」,在[]外面是「字符串开头」,千万别搞混。
2.匹配「数量」的核心量词
| 符号 | 大白话解释 | 极简例子(测试文本:ac abc abbc abbbc) | 匹配结果 |
|---|---|---|---|
* | 匹配前面的字符,出现 0 次或多次(可有可无,越多越好) | ab*c | 匹配ac、abc、abbc、abbbc |
+ | 匹配前面的字符,出现 1 次或多次(至少 1 次,不能没有) | ab+c | 匹配abc、abbc、abbbc,不匹配ac |
? | 匹配前面的字符,出现 0 次或 1 次(最多 1 次,也就是「可选」) | ab?c | 匹配ac、abc,不匹配abbc |
{n} | 匹配前面的字符,正好出现 n 次(超高频!) | \d{11} | 匹配正好 11 个数字(手机号核心规则) |
{n,} | 匹配前面的字符,至少出现 n 次 | \d{6,} | 匹配至少 6 个数字 |
{n,m} | 匹配前面的字符,出现 n~m 次(闭区间) | \d{6,12} | 匹配 6 到 12 个数字(密码长度规则) |
WARNING
- 解决「要找的字符,重复出现多少次」的问题,必须跟在「单个字符符号」后面使用
*=+∪?,也就是说*等于+和?的并集- 贪婪模式 vs 非贪婪模式
- 量词默认是贪婪模式:会尽可能匹配最长的符合规则的内容
- 例子:正则
a.*b,测试文本a123b456b,会匹配整个a123b456b,而不是最短的a123b- 非贪婪模式:在量词后面加
?,会匹配最短的符合规则的内容
- 例子:正则
a.*?b,测试文本a123b456b,只会匹配a123b
进阶
1.匹配「位置」的锚点
NOTE
不匹配具体的字符,只匹配「文本的位置」,核心用来做格式验证
| 符号 | 大白话解释 | 高频用法 |
|---|---|---|
^ | 匹配整个字符串的开头 | ^1:只有以 1 开头的文本才会被匹配 |
$ | 匹配整个字符串的结尾 | \d$:只有以数字结尾的文本才会被匹配 |
\b | 匹配单词的边界(单词和空格 / 标点之间的位置) | \bhello\b:匹配hello world里的 hello,不匹配helloworld里的 hello |
WARNING
\b是保证匹配的是整体,而不是中间片段,具体的整体匹配对象应该在两个\b之间。- 经典案例:验证 11 位国内手机号
- 正确正则:
^1[3-9]\d{9}$ - 解释:
^开头必须是 1,第二位是 3-9(国内手机号规则),后面跟 9 个数字,$结尾,确保整个文本正好 11 位,不会匹配到 12 位数字里的片段。
- 正确正则:
2.分组与分支
1. 分支 |
大白话:或者,匹配左边的规则,或者匹配右边的规则。
例子:abc|def,匹配abc或者def;jpg|png|gif,匹配三种图片后缀。
2. 分组 ()
核心作用有两个,是正则进阶的核心:
-
把规则当成一个整体
例子:
(ab)+,匹配ab、abab、ababab(ab 重复 1 次或多次);如果不加括号ab+,是匹配a后面跟 1 个或多个b,比如ab、abb、abbb,完全是两个意思。 -
捕获分组,支持反向引用
括号里匹配到的内容会被自动存起来,从左到右,第一个括号是
\1(匹配时引用)/$1(替换时引用),第二个是\2/$2,以此类推。超实用经典案例:日期格式批量转换
需求:把
2024-05-20改成05/20/2024正则:
(\d{4})-(\d{2})-(\d{2})替换内容:
$2/$3/$1解释:第一个括号捕获年份
2024(2),第三个捕获日期20($3),替换时直接调换顺序即可。
补充:非捕获分组
(?:)只把规则当整体,不存储匹配内容,不占用分组编号,适合不需要反向引用的场景,比如
(?:ab)+,匹配结果和(ab)+一致,但不会存储ab到分组里。

















