RegExp
Baseline 广泛可用 *
RegExp 对象用于将文本与模式进行匹配。
有关正则表达式的介绍,请阅读 JavaScript 指南中的正则表达式一章。有关正则表达式语法的详细信息,请阅读正则表达式参考。
描述
字面量语法和构造函数
创建 RegExp 对象有两种方式:字面量语法和构造函数。
以下三个表达式创建相同的正则表达式对象:
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。
使用构造函数时,需要遵循正常的字符串转义规则(在字符串中包含特殊字符时,在特殊字符前加上 \)。
例如,以下是等效的
const re = /\w+/;
// OR
const re = new RegExp("\\w+");
正则表达式的特殊处理
注意: 判断一个东西是否是“正则表达式”可以通过鸭子类型来完成。它不必是 RegExp!
一些内置方法会特殊处理正则表达式。它们通过多个步骤来判断 x 是否是正则表达式:
x必须是一个对象(而不是原始值)。- 如果
x[Symbol.match]不是undefined,则检查它是否为真值。 - 否则,如果
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()、startsWith()和includes()如果第一个参数是正则表达式,则会抛出TypeError。String.prototype.matchAll()和replaceAll()会检查第一个参数是否为正则表达式,如果是,则在调用其[Symbol.matchAll]()或[Symbol.replace]()方法之前,检查 global 标志是否已设置。RegExp()构造函数只有当pattern是正则表达式(以及其他一些条件)时,才会直接返回pattern参数。如果pattern是正则表达式,它还会询问pattern的source和flags属性,而不是将pattern强制转换为字符串。
例如,String.prototype.endsWith() 会将所有输入强制转换为字符串,但如果参数是正则表达式,它会抛出错误,因为它只设计用于匹配字符串,而使用正则表达式很可能是开发人员的错误。
"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 对象),但它几乎可以用于其他所有用途。
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 来指示正则表达式模式中相应匹配括号的结果。
const re = /(\w+)\s(\w+)/;
const str = "Maria Cruz";
const newStr = str.replace(re, "$2, $1");
console.log(newStr);
这将显示 "Cruz, Maria"。
使用正则表达式拆分具有不同行尾/行尾/换行的行
默认的行尾因平台(Unix、Windows 等)而异。此示例中提供的行拆分适用于所有平台。
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 模式)。
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 开始匹配来在目标字符串中执行粘性匹配。
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 位置或之后。
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 的字符;例如,a 到 z、A 到 Z、0 到 9 和 _。
要匹配其他语言(如西里尔语或希伯来语)的字符,请使用 \uHHHH,其中 HHHH 是字符的十六进制 Unicode 值。
此示例演示如何从单词中分离出 Unicode 字符。
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 提取子域名
const url = "http://xxx.domain.com";
console.log(/^https?:\/\/(.+?)\./.exec(url)[1]); // 'xxx'
注意: 相对于使用正则表达式解析 URL,通常使用浏览器内置的 URL 解析器(通过 URL API)更好。
从动态输入构建正则表达式
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 而不是空字符串。
// 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)。