JavaScript regex:测试、提取与替换字符串

JavaScript regex 用于按模式匹配文本,可完成校验、提取和替换。只要输入遵循可预测格式(如日期、ID、编码),正则表达式就能检测匹配或提取关键片段。圆括号中的捕获组会隔离匹配子串,让一个模式直接返回结构化数据,而不必手动拆分字符串。

JavaScript Regex 提取模式示例

输出:

输出将显示在这里...

输出:

包含日期: true
提取结果: 2024/03/15
替换后: 订单 #A-123 已于 2024/03/15 发货

这个示例如何工作

  1. /(\d{4})-(\d{2})-(\d{2})/ 定义了一个匹配 ISO 风格日期的正则字面量。\d{4} 精确匹配 4 位数字;圆括号创建用于年份、月份和日期的捕获组。
  2. datePattern.test(text) 会在字符串任意位置匹配成功时返回 true,但不会返回匹配详情。
  3. text.match(datePattern) 返回一个数组:索引 0 是完整匹配,后续依次是每个捕获组。若未匹配则返回 null,因此解析用户输入时应先做判断再解构。
  4. text.replace(datePattern, "$1/$2/$3") 替换匹配到的子串。$1$2$3 会插入捕获组(年、月、日)。

什么是 JavaScript 正则表达式?

JavaScript 正则表达式是 RegExp 对象(常称为 JavaScript regexp),用于匹配字符串中的字符组合。你可以用字面量(/pattern/flags)或 RegExp 构造函数(new RegExp("pattern", "flags"))创建正则。引擎按从左到右扫描,默认返回首个匹配;设置全局标志 g 后会继续查找后续匹配。

JavaScript Regex 的常见错误

testexec 中使用带全局标志的正则。

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

使用 gy 时,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 构造函数,例如匹配用户输入的搜索词。其余情况优先使用字面量:无需双重转义,而且语法错误会在解析期而不是运行期暴露。