外观
正则表达式食谱
约 1314 字
正则这工具,用的频率不高,但每次用都省大时间:一次校验、一次批量替换、 一次日志解析,手写循环能写半小时,它一行搞定。问题是语法容易忘, 这篇当菜谱,用到什么查什么。
一、最小可用语法
. 任意一个字符(换行符除外,加 s 标志后包括)
\d 数字 0-9
\w 字母、数字、下划线
\s 空白(空格、Tab、换行)
\D \W \S 上面三个的「不是」
[abc] a、b、c 中的任意一个
[^abc] 除了它们仨
[a-z0-9] 区间组合
* 前面的东西重复 0 次或多次
+ 重复 1 次或多次
? 重复 0 次或 1 次
{3} 正好 3 次
{3,} 至少 3 次
{3,5} 3 到 5 次
^ 开头(方括号里是「非」的意思)
$ 结尾
| 或:cat|dog
( ) 分组,还能把匹配到的部分「捕获」出来图:最常用的几类模式,忘了就回来查
二、常用模式速查
手机号(中国大陆,简单版):
/^1[3-9]\d{9}$/严格版号段一大堆,业务上「能拦住乱填的」就行,别追求完美。
邮箱:
/^[\w.-]+@[\w-]+(\.[\w-]+)+$/这个不追求 RFC 完备(那个正规军表达式长得离谱),够挡住 99% 的错填。
URL:
/^(https?):\/\/[\w.-]+(:\d+)?(\/[^\s]*)?$/IPv4(宽松):
/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/它不校验 0-255 的范围(999.999.999.999 也能过),要严格校验范围的话, 后面提。
日期(YYYY-MM-DD):
/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/月份限制 01-12,日期 01-31。2 月 30 号这种它不管,真要校验日期合法性, 交给 new Date() 更靠谱。
去掉 HTML 标签(粗暴版):
str.replace(/<[^>]+>/g, '')再次强调粗暴版,解析 HTML 请用正经解析器。
三、分组与捕获
圆括号不只是分组,还能把匹配到的片段拿出来:
const m = '2026-10-21'.match(/^(\d{4})-(\d{2})-(\d{2})$/)
// m[1] = '2026', m[2] = '10', m[3] = '21'JS 里用解构更爽:
const [, year, month, day] = '2026-10-21'.match(/^(\d{4})-(\d{2})-(\d{2})$/)替换时可以用 $1、$2 引用捕获组。把日期格式从 2026-10-21 改成 21/10/2026:
'2026-10-21'.replace(/^(\d{4})-(\d{2})-(\d{2})$/, '$3/$2/$1')
// '21/10/2026'不需要捕获的分组加 (?:...),叫非捕获组,只分组不占编号:
/(?:ab)+(c)/ // 只有 c 是 $1命名捕获组(ES2018+),可读性更好:
const m = /^(?<year>\d{4})-(?<month>\d{2})$/.exec('2026-10')
// m.groups.year === '2026'四、标志位
/pattern/g // global:全局匹配,不只找第一个
/pattern/i // ignoreCase:忽略大小写
/pattern/m // multiline:^ $ 匹配每一行的开头结尾,不只是整串
/pattern/s // dotAll:. 也能匹配换行符
/pattern/u // unicode:正确处理 emoji、生僻字
/pattern/y // sticky:从上次匹配结束的位置开始找两个高频翻车点:
- 忘了
/g:replace只替换第一个,排查半天; test配合/g会「记忆」位置:/a/g.test('aa')第一次 true, 第二次 false,因为lastIndex前进了。所以test别带/g。
五、性能:灾难性回溯
这是正则最著名的坑。看这个「看起来人畜无害」的模式:
/^(a+)+$/拿它匹配一串 a 后面跟一个 b 的字符串,比如 'aaaaaaaaaaaaaaaaaaaaab'。 回立刻卡死。为什么:(a+)+ 匹配同一串 a 有无穷多种拆法, 回溯时要穷举这些拆法,数量随长度指数爆炸。
规避原则:
- 别写嵌套量词(
(x+)+、(x*)*、(x+)*这类); - 两组量词之间加「锚定物」,比如
(a+)+b改写成a+b; - 复杂校验拆成几步,正则干一部分,代码逻辑干一部分;
- 在线测试正则,用不支持回溯炸弹的测试数据,别在生产代码里试。
六、调试工具
- regex101.com:业界公认最好用,逐字符解释匹配过程, 支持多种方言(JS/Python/PCRE);
- regexr.com:交互更现代,社区示例多;
- VS Code 搜
regex101扩展,编辑器内直接测。
拿不准的模式先上 regex101 跑一遍再上线,比在生产日志里试安全得多。
七、一份「人话翻译」练习
最后留个练习,把这段「人话」翻成正则: 匹配一段 IPv4,且每段 0-255:
0-199 :[01]?\d?\d(宽松点也行,别太纠结)
200-249:2[0-4]\d
250-255:25[0-5]组合起来:
/^((25[0-5]|2[0-4]\d|[01]?\d?\d)\.){3}(25[0-5]|2[0-4]\d|[01]?\d?\d)$/能看懂这个,日常正则就毕业了。看不懂没关系,把前面速查表用熟, 遇到具体场景现查,程序员不是背正则的机器。
小结
正则的正确用法是:常用模式背十几条,复杂场景现场查,性能红线不碰 嵌套量词。它是个省时间的工具,别把它当成炫技的舞台 —— 能一条正则解决别写三十行,但该用代码逻辑的地方也别硬套正则。