RegExp

Baseline 广泛可用 *

此特性已相当成熟,可在许多设备和浏览器版本上使用。自 ⁨2015 年 7 月⁩以来,各浏览器均已提供此特性。

* 此特性的某些部分可能存在不同级别的支持。

RegExp 对象用于将文本与模式进行匹配。

有关正则表达式的介绍,请阅读 JavaScript 指南中的正则表达式一章。有关正则表达式语法的详细信息,请阅读正则表达式参考

描述

字面量语法和构造函数

创建 RegExp 对象有两种方式:字面量语法构造函数

  • 字面量语法在两个斜杠之间包含一个模式,后面跟着可选的标志,位于第二个斜杠之后。
  • 构造函数将其第一个参数作为字符串或 RegExp 对象,将其第二个参数作为可选的标志字符串。

以下三个表达式创建相同的正则表达式对象:

js
const re = /ab+c/i; // literal notation
// OR
const re = new RegExp("ab+c", "i"); // constructor with string pattern as first argument
// OR
const re = new RegExp(/ab+c/, "i"); // constructor with regular expression literal as first argument

正则表达式在使用之前必须经过编译。这个过程可以提高它们的匹配效率。有关此过程的更多信息可以在 dotnet 文档中找到。

字面量语法在表达式求值时编译正则表达式。另一方面,RegExp 对象的构造函数 new RegExp('ab+c') 会在运行时编译正则表达式。

当你希望从动态输入构建正则表达式时,可以使用字符串作为 RegExp() 构造函数的第一个参数。

构造函数中的标志

表达式 new RegExp(/ab+c/, flags) 将使用第一个参数的源和第二个参数提供的标志创建一个新的 RegExp

使用构造函数时,需要遵循正常的字符串转义规则(在字符串中包含特殊字符时,在特殊字符前加上 \)。

例如,以下是等效的

js
const re = /\w+/;
// OR
const re = new RegExp("\\w+");

正则表达式的特殊处理

注意: 判断一个东西是否是“正则表达式”可以通过鸭子类型来完成。它不必是 RegExp

一些内置方法会特殊处理正则表达式。它们通过多个步骤来判断 x 是否是正则表达式:

  1. x 必须是一个对象(而不是原始值)。
  2. 如果 x[Symbol.match] 不是 undefined,则检查它是否为真值
  3. 否则,如果 x[Symbol.match]undefined,则检查 x 是否是用 RegExp 构造函数创建的。(这一步很少发生,因为如果 x 是一个未被篡改的 RegExp 对象,它应该有一个 Symbol.match 属性。)

请注意,在大多数情况下,它会通过 Symbol.match 检查,这意味着:

  • 一个真实的 RegExp 对象的 Symbol.match 属性的值是假值但不是 undefined(即使其他一切都完好无损,如exec[Symbol.replace]()),也可以像它不是正则表达式一样使用。
  • 一个没有 RegExp 对象的 Symbol.match 属性将被视为正则表达式。

做出这个选择是因为 [Symbol.match]() 是最能指示某个东西是否打算用于匹配的属性。(exec 也可以使用,但因为它不是一个 Symbol 属性,会导致太多的误报。)特殊处理正则表达式的地方包括:

例如,String.prototype.endsWith() 会将所有输入强制转换为字符串,但如果参数是正则表达式,它会抛出错误,因为它只设计用于匹配字符串,而使用正则表达式很可能是开发人员的错误。

js
"foobar".endsWith({ toString: () => "bar" }); // true
"foobar".endsWith(/bar/); // TypeError: First argument to String.prototype.endsWith must not be a regular expression

你可以通过将 [Symbol.match] 设置为非 undefined假值来绕过此检查。这意味着该正则表达式不能用于 String.prototype.match()(因为没有 [Symbol.match]match() 将使用 re.toString() 添加的两个斜杠来构造新的 RegExp 对象),但它几乎可以用于其他所有用途。

js
const re = /bar/g;
re[Symbol.match] = false;
"/bar/g".endsWith(re); // true
re.exec("bar"); // [ 'bar', index: 0, input: 'bar', groups: undefined ]
"bar & bar".replace(re, "foo"); // 'foo & foo'

类 Perl 的 RegExp 属性

请注意,RegExp 的许多属性都有长名称和短名称(类 Perl)。这两个名称总是指同一个值。(Perl 是 JavaScript 模仿其正则表达式的编程语言。)另请参阅已弃用的 RegExp 属性

构造函数

RegExp()

创建新的 RegExp 对象。

静态属性

RegExp.$1, …, RegExp.$9 已弃用

包含带括号子字符串匹配的静态只读属性。

RegExp.input ($_) 已弃用

一个静态属性,包含正则表达式成功匹配的最后一个字符串。

RegExp.lastMatch ($&) 已弃用

一个静态只读属性,包含最后匹配的子字符串。

RegExp.lastParen ($+) 已弃用

一个静态只读属性,包含最后一个带括号的子字符串匹配。

RegExp.leftContext ($`) 已弃用

一个静态只读属性,包含最近匹配之前的子字符串。

RegExp.rightContext ($') 已弃用

一个静态只读属性,包含最近匹配之后的子字符串。

RegExp[Symbol.species]

用于创建派生对象的构造函数。

静态方法

RegExp.escape()

转义字符串中任何潜在的正则表达式语法字符,并返回一个新字符串,该字符串可以安全地用作 RegExp() 构造函数的字面量模式。

实例属性

这些属性定义在 RegExp.prototype 上,并由所有 RegExp 实例共享。

RegExp.prototype.constructor

创建实例对象的构造函数。对于 RegExp 实例,初始值为 RegExp 构造函数。

RegExp.prototype.dotAll

. 是否匹配换行符。

RegExp.prototype.flags

包含 RegExp 对象的标志的字符串。

RegExp.prototype.global

是针对字符串中的所有可能匹配测试正则表达式,还是只针对第一个匹配。

RegExp.prototype.hasIndices

正则表达式结果是否暴露捕获子字符串的起始和结束索引。

RegExp.prototype.ignoreCase

在字符串中尝试匹配时是否忽略大小写。

RegExp.prototype.multiline

是否跨多行搜索字符串。

RegExp.prototype.source

模式的文本。

RegExp.prototype.sticky

搜索是否具有粘性。

RegExp.prototype.unicode

是否启用 Unicode 功能。

RegExp.prototype.unicodeSets

是否启用 v 标志,它是 u 模式的升级。

这些属性是每个 RegExp 实例的自有属性。

lastIndex

下一个匹配开始的索引。

实例方法

RegExp.prototype.compile() 已弃用

在脚本执行期间(重新)编译正则表达式。

RegExp.prototype.exec()

在其字符串参数中执行搜索匹配。

RegExp.prototype.test()

在其字符串参数中测试匹配。

RegExp.prototype.toString()

返回表示指定对象的字符串。覆盖 Object.prototype.toString() 方法。

RegExp.prototype[Symbol.match]()

对给定字符串执行匹配并返回匹配结果。

RegExp.prototype[Symbol.matchAll]()

返回正则表达式对字符串的所有匹配项。

RegExp.prototype[Symbol.replace]()

用新子字符串替换给定字符串中的匹配项。

RegExp.prototype[Symbol.search]()

在给定字符串中搜索匹配项并返回模式在字符串中找到的索引。

RegExp.prototype[Symbol.split]()

通过将字符串拆分为子字符串,将给定字符串拆分为数组。

示例

使用正则表达式更改数据格式

以下脚本使用 String.prototype.replace() 方法匹配 first last 格式的名称,并将其输出为 last, first 格式。

在替换文本中,脚本使用 $1$2 来指示正则表达式模式中相应匹配括号的结果。

js
const re = /(\w+)\s(\w+)/;
const str = "Maria Cruz";
const newStr = str.replace(re, "$2, $1");
console.log(newStr);

这将显示 "Cruz, Maria"

使用正则表达式拆分具有不同行尾/行尾/换行的行

默认的行尾因平台(Unix、Windows 等)而异。此示例中提供的行拆分适用于所有平台。

js
const text = "Some text\nAnd some more\r\nAnd yet\nThis is the end";
const lines = text.split(/\r?\n/);
console.log(lines); // [ 'Some text', 'And some more', 'And yet', 'This is the end' ]

请注意,正则表达式中模式的顺序很重要。

在多行上使用正则表达式

默认情况下,. 字符不匹配换行符。要使其匹配换行符,请使用 s 标志(dotAll 模式)。

js
const s = "Please yes\nmake my day!";

s.match(/yes.*day/);
// Returns null

s.match(/yes.*day/s);
// Returns ["yes\nmake my day"]

使用带粘性标志的正则表达式

sticky 标志表示正则表达式通过尝试从 RegExp.prototype.lastIndex 开始匹配来在目标字符串中执行粘性匹配。

js
const str = "#foo#";
const regex = /foo/y;

regex.lastIndex = 1;
regex.test(str); // true
regex.lastIndex = 5;
regex.test(str); // false (lastIndex is taken into account with sticky flag)
regex.lastIndex; // 0 (reset after match failure)

粘性标志和全局标志之间的区别

使用粘性标志 y 时,下一个匹配必须发生在 lastIndex 位置,而使用全局标志 g 时,匹配可以发生在 lastIndex 位置或之后。

js
const re = /\d/y;
let r;
while ((r = re.exec("123 456"))) {
  console.log(r, "AND re.lastIndex", re.lastIndex);
}

// [ '1', index: 0, input: '123 456', groups: undefined ] AND re.lastIndex 1
// [ '2', index: 1, input: '123 456', groups: undefined ] AND re.lastIndex 2
// [ '3', index: 2, input: '123 456', groups: undefined ] AND re.lastIndex 3
//  … and no more match.

使用全局标志 g 时,将匹配所有 6 位数字,而不仅仅是 3 位。

正则表达式和 Unicode 字符

\w\W 只匹配基于 ASCII 的字符;例如,azAZ09_

要匹配其他语言(如西里尔语或希伯来语)的字符,请使用 \uHHHH,其中 HHHH 是字符的十六进制 Unicode 值。

此示例演示如何从单词中分离出 Unicode 字符。

js
const text = "Образец text на русском языке";
const regex = /[\u0400-\u04ff]+/g;

const match = regex.exec(text);
console.log(match[0]); // 'Образец'
console.log(regex.lastIndex); // 7

const match2 = regex.exec(text);
console.log(match2[0]); // 'на' (did not log 'text')
console.log(regex.lastIndex); // 15

// and so on

Unicode 属性转义功能提供了一种更简单的方法来定位特定的 Unicode 范围,允许使用 \p{scx=Cyrl}(匹配任何西里尔字母)或 \p{L}/u(匹配任何语言的字母)等语句。

从 URL 提取子域名

js
const url = "http://xxx.domain.com";
console.log(/^https?:\/\/(.+?)\./.exec(url)[1]); // 'xxx'

注意: 相对于使用正则表达式解析 URL,通常使用浏览器内置的 URL 解析器(通过 URL API)更好。

从动态输入构建正则表达式

js
const breakfasts = ["bacon", "eggs", "oatmeal", "toast", "cereal"];
const order = "Let me get some bacon and eggs, please";

order.match(new RegExp(`\\b(${breakfasts.join("|")})\\b`, "g"));
// Returns ['bacon', 'eggs']

规范

规范
ECMAScript® 2026 语言规范
# sec-regexp-regular-expression-objects

浏览器兼容性

Firefox 特有注意事项

从 Firefox 34 开始,在捕获组带有量词且阻止其执行的情况下,捕获组的匹配文本现在是 undefined 而不是空字符串。

js
// Firefox 33 or older
"x".replace(/x(.)?/g, (m, group) => {
  console.log(`group: ${JSON.stringify(group)}`);
});
// group: ""

// Firefox 34 or newer
"x".replace(/x(.)?/g, (m, group) => {
  console.log(`group: ${group}`);
});
// group: undefined

请注意,由于 Web 兼容性,RegExp.$N 仍将返回空字符串而不是 undefined (bug 1053944)。

另见