JavaScript regex:测试、提取与替换字符串
JavaScript regex 用于按模式匹配文本,可完成校验、提取和替换。只要输入遵循可预测格式(如日期、ID、编码),正则表达式就能检测匹配或提取关键片段。圆括号中的捕获组会隔离匹配子串,让一个模式直接返回结构化数据,而不必手动拆分字符串。
JavaScript Regex 提取模式示例
输出:
输出将显示在这里...
输出:
包含日期: true
提取结果: 2024/03/15
替换后: 订单 #A-123 已于 2024/03/15 发货
这个示例如何工作
/(\d{4})-(\d{2})-(\d{2})/定义了一个匹配 ISO 风格日期的正则字面量。\d{4}精确匹配 4 位数字;圆括号创建用于年份、月份和日期的捕获组。datePattern.test(text)会在字符串任意位置匹配成功时返回true,但不会返回匹配详情。text.match(datePattern)返回一个数组:索引0是完整匹配,后续依次是每个捕获组。若未匹配则返回null,因此解析用户输入时应先做判断再解构。text.replace(datePattern, "$1/$2/$3")替换匹配到的子串。$1、$2、$3会插入捕获组(年、月、日)。
什么是 JavaScript 正则表达式?
JavaScript 正则表达式是 RegExp 对象(常称为 JavaScript regexp),用于匹配字符串中的字符组合。你可以用字面量(/pattern/flags)或 RegExp 构造函数(new RegExp("pattern", "flags"))创建正则。引擎按从左到右扫描,默认返回首个匹配;设置全局标志 g 后会继续查找后续匹配。
JavaScript Regex 的常见错误
在 test 或 exec 中使用带全局标志的正则。
const re = /\d+/g;
console.log(re.test("abc 123")); // true
console.log(re.test("abc 123")); // false(lastIndex 已前移)
re.lastIndex = 0;
console.log(re.test("abc 123")); // true
使用 g 或 y 时,test/exec 会通过 lastIndex 保存状态。做布尔判断时应重置它,或直接不用 g。
在 new RegExp() 里忘记双重转义。
new RegExp("\d+"); // 模式实际是 "d+"
new RegExp("\\d+"); // 一个或多个数字
在字符串字面量中,\\ 才会生成单个反斜杠,因此正则引擎接收到的是 \d 而不是 d。
Regex 字面量 vs RegExp 构造函数
正则字面量 (/pattern/) | new RegExp(pattern) |
|---|---|
| 加载时解析;语法错误可提前发现 | 运行时编译;执行到该行才会抛错 |
| 不需要字符串转义 | 需要双反斜杠(\\d) |
| 模式在源码中固定 | 模式可由变量动态构建 |
静态模式优先使用字面量。模式包含动态值时使用构造函数,但必须先转义用户输入,避免正则注入和意外元字符。
const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const re = new RegExp(escapeRegExp("a+b?"), "i");
更多示例
用 replaceAll 替换所有匹配:
const masked = "卡号 4111-1111-1111-1111".replaceAll(/\d{4}/g, "****");
console.log(masked); // "卡号 ****-****-****-****"
当搜索参数是正则时,replaceAll 要求带 g 标志;省略 g 会抛出 TypeError。
用 matchAll 提取全部匹配:
const tags = [...("#js #regex #es2022".matchAll(/#(\w+)/g))];
console.log(tags.map(m => m[1])); // ["js", "regex", "es2022"]
matchAll 返回由匹配数组组成的迭代器,每项都包含捕获组;展开成数组后可完整访问每个结果。
FAQ
如何在 JavaScript 中测试正则表达式?
调用 regex.test(string) 获取布尔结果,或使用 string.match(regex) 获取匹配详情。需要多个匹配时,使用带 g 标志的 string.matchAll(regex),它返回包含全部匹配数组(含捕获组)的迭代器。
JavaScript 支持后行断言(lookbehind)吗?
支持。正向后行断言 (?<=...) 和负向后行断言 (?<!...) 在大多数现代 JavaScript 引擎中可用,但旧浏览器和某些嵌入式运行时可能抛出语法错误。
什么时候应使用 new RegExp() 而不是字面量?
当模式在编写代码时无法确定时使用 RegExp 构造函数,例如匹配用户输入的搜索词。其余情况优先使用字面量:无需双重转义,而且语法错误会在解析期而不是运行期暴露。