JavaScript正则核心在于理解标志位、捕获组及替换符号含义;创建用字面量或RegExp构造函数(注意双反斜杠);match()行为依g和捕获组而异;replace()中$有特殊意义;慎用正则解析结构化文本。

JavaScript 中正则匹配和替换的核心是 RegExp 对象和字符串的 match()、replace() 等方法。关键不在“会不会写正则”,而在于“是否理解标志位、捕获组、替换字符串中特殊符号的含义”——多数问题都出在这里。
如何正确创建正则表达式并避免常见语法错误
两种创建方式:字面量 /pattern/flags 和构造函数 new RegExp(pattern, flags)。前者更常用,但动态拼接时必须用后者;注意构造函数中反斜杠要双写。
- 字面量中不需要引号:
/\d+/g✅,写成"/\d+/g"❌(变成普通字符串) - 构造函数中转义字符要加倍:
new RegExp("\\d+", "g")✅,new RegExp("\d+", "g")❌(\d被 JS 字符串提前解析为非法转义) - 全局匹配必须加
g标志,否则match()只返回第一个结果且忽略后续 - 忽略大小写用
i,多行模式用m(影响^和$),但m在 JS 中对.无影响(不匹配换行符)
String.prototype.match() 的三种行为差异
返回值类型取决于正则是否有 g 标志和是否使用括号捕获:
- 有
g:返回纯匹配数组,如"a1b2c3".match(/\d/g)→["1", "2", "3"] - 无
g且无捕获组:返回单个匹配对象,含index和input属性,如"a1b2".match(/\d/)→["1", index: 1, input: "a1b2"] - 无
g但有捕获组:返回带子匹配的数组,["完整匹配", "组1", "组2"],如"abc".match(/(a)(b)/)→["ab", "a", "b"]
想稳定获取所有捕获结果?别依赖 match(),改用 matchAll()(返回迭代器,需展开):
立即学习“Java免费学习笔记(深入)”;
const str = "id:123,name:abc";
const regex = /(\w+):(\w+)/g;
[...str.matchAll(regex)].map(m => ({ key: m[1], value: m[2] }));
// → [{ key: "id", value: "123" }, { key: "name", value: "abc" }]
String.prototype.replace() 中的替换逻辑陷阱
替换值可以是字符串或函数,但字符串里的 $ 符号有特殊含义,极易误用:
-
$&表示整个匹配,$1表示第一个捕获组,$`是匹配前内容,$'是匹配后内容 - 想字面量输出
$1?必须写成$$1(两个$→ 一个字面量$) - 函数作为第二个参数时,参数顺序固定:
(match, group1, group2, ..., offset, string),其中match是完整匹配字符串 - 全局替换必须用
g标志,否则只替换第一个
示例:把 url("path/to.css") 中的路径提取出来并补上前缀:
const css = 'body { background: url("main.css"); }';
css.replace(/url\("([^"]+)"\)/g, (m, path) => `url("/static/${path}")`);
// → 'body { background: url("/static/main.css"); }'
性能与兼容性需要注意的边界点
正则本身开销不大,但不当用法会引发意外行为:
-
replace()对空字符串匹配(如/^/g)会在每个字符前插入内容,小心无限循环风险 -
matchAll()不支持 IE,需要polyfill或降级为exec()循环 - 长文本 + 复杂正则(尤其嵌套量词)可能触发回溯爆炸,用
/(? 这类负向断言前先确认执行环境支持(Node.js ≥ 9.0,Chrome ≥ 62) - Unicode 字符(如 emoji、中文)建议加
u标志,否则.和\w可能无法正确匹配
真正难的不是写出正则,而是判断该不该用正则——比如解析 HTML 用 DOMParser,解析 CSV 用专用库,别硬套 split(/,(?=(?:[^"]*"[^"]*")*[^"]*$)/) 这种“正则奇迹”。










