正则表达式
正则表达式用一套模式描述"字符串长什么样",解决文本的匹配、提取、替换三类问题。它是处理用户输入校验、日志解析、爬虫提取、批量替换的利器:一段 20 行的正则逻辑,用 if-else 手写可能上百行还容易漏边界。代价是语法密集、可读性差——所以写正则的原则是"够用就行,复杂逻辑拆开写"。
提示
正则三步走:先想清楚"要匹配的字符长什么样",再选基础语法(字符类/量词/锚点),最后用测试工具验证边界(如 regex101)。不要追求一条正则解决所有问题。
基础语法
| 语法 | 含义 | 例子 |
|---|---|---|
\d \w \s | 数字 / 字母数字下划线 / 空白 | \d+ 匹配连续数字 |
[abc] [a-z] | 字符类:任一 / 范围 | [a-zA-Z] 匹配字母 |
. | 任意字符(除换行) | a.c 匹配 abc、a1c |
^ $ | 行首 / 行尾锚点 | ^start、end$ |
* + ? | 0 次或多次 / 1 次或多次 / 0 次或 1 次 | ab*c、ab+c、ab?c |
{n,m} | 重复 n 到 m 次 | \d{3,5} 匹配 3-5 位数字 |
(ab) | 捕获组:分组并记录内容 | (\d{4})-(\d{2}) |
| | 或 | cat|dog 匹配 cat 或 dog |
\b | 单词边界 | \bword\b 匹配独立单词 |
转义
\d 等反斜杠序列在字符串字面量里会先被 JavaScript 转义("\d" 中的 \d 不合法),所以用字面量写法 /pattern/ 最稳妥,需要动态构建模式时才用 new RegExp('pattern')。
JavaScript 用法
// 创建
const regex = /pattern/flags; // 字面量(推荐)
const regex2 = new RegExp('pattern'); // 动态构建
// 三个常用方法
'Hello World'.match(/\w+/g); // ['Hello', 'World'] 提取
'Hello'.replace(/l/g, 'x'); // 'Hexxo' 替换
'Hello'.search(/world/i); // -1(未找到返回 -1)
// 常用标志
const r = /test/gi; // g=全局(不止匹配第一处),i=忽略大小写,m=多行模式字符串方法 vs 正则方法
str.match(regex) 返回匹配结果数组;str.replace(regex, fn) 的第二个参数可以是回调函数(对每处匹配做处理,如把数字格式化);regex.test(str) 只判断"有没有匹配",返回布尔值,性能最快,适合校验场景。
捕获组与反向引用
捕获组 (...) 除了分组,还能把匹配的内容"记下来"复用:
// 替换中引用捕获组:$1、$2 对应第 1、2 个组
'2026-08-13'.replace(/(\d{4})-(\d{2})-(\d{2})/, '$1/$2/$3');
// '2026/08/13'
// 回调函数拿到完整匹配和每个组
'abc123'.replace(/([a-z]+)(\d+)/, (match, letters, digits) =>
letters.toUpperCase() + digits);
// 'ABC123'非捕获组与前瞻
不需要"记住"内容时用 (?:...) 非捕获组(省内存、更清晰);(?=...) 前瞻断言"后面跟着什么但不消费":\d+(?=元) 匹配"10 元"中的 10 但不包括"元"。这些属于进阶语法,用到再查即可。
常用模式
| 场景 | 模式 | 说明 |
|---|---|---|
| 手机号(11 位) | ^1[3-9]\d{9}$ | 1 开头,第二位 3-9,共 11 位 |
| 邮箱 | ^[\w.+-]+@[\w-]+\.[\w.-]+$ | 用户名@域名.后缀 |
| IPv4 | ^(\d{1,3}\.){3}\d{1,3}$ | 四段数字(严格校验需逐段 0-255) |
| 数字金额 | ^\d+(\.\d{1,2})?$ | 整数或最多两位小数 |
| 身份证号 | ^\d{17}[\dXx]$ | 18 位,末位可为 X |
// 手机号校验:^ 和 $ 确保"整个字符串就是手机号"而非"包含手机号"
const isPhone = (s) => /^1[3-9]\d{9}$/.test(s);
isPhone('13800138000'); // true
isPhone('12345678901'); // false(第二位不是 3-9)贪婪匹配与回溯灾难
量词默认贪婪(尽可能多匹配):<.+> 匹配 <a>1</a> 会吞到最后一个 >。用 .+? 改懒惰可解决。更危险的是嵌套结构上的复杂模式(如 (a+)+b 匹配失败时的指数级回溯),会让程序卡死——对不可信输入做校验时,避免深层嵌套的量词组合,或改用专门的解析器。
适用场景
| 场景 | 用法 |
|---|---|
| 表单校验 | test() 判断手机号、邮箱、密码强度 |
| 日志解析 | match 提取时间、级别、IP 字段 |
| 批量替换 | replace 统一格式、脱敏(手机号中间四位打码) |
| 文本清洗 | 去空白、去 HTML 标签、提取链接 |
正则不是 JavaScript 专属——Git 的提交信息过滤、Markdown 文档中的链接匹配、Mermaid 语法解析都依赖正则思想。它是所有文本处理场景的通用语言。