RegExp

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

¥The RegExp object is used for matching text with a pattern.

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

¥For an introduction to regular expressions, read the Regular expressions chapter in the JavaScript guide. For detailed information of regular expression syntax, read the regular expression reference.

描述

¥Description

文字表示法和构造函数

¥Literal notation and constructor

创建 RegExp 对象有两种方法:文字符号和构造函数。

¥There are two ways to create a RegExp object: a literal notation and a constructor.

  • 文字表示法采用两个斜杠之间的模式,第二个斜杠后面紧接着可选的 flags
  • 构造函数将字符串或 RegExp 对象作为其第一个参数,将可选的 flags 字符串作为其第二个参数。

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

¥The following three expressions create the same regular expression object:

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

在使用正则表达式之前,必须先对其进行编译。这个过程使他们能够更有效地进行比赛。有关该过程的更多信息可以在 点网文档 中找到。

¥Before regular expressions can be used, they have to be compiled. This process allows them to perform matches more efficiently. More about the process can be found in dotnet docs.

当计算表达式时,文字表示法会导致正则表达式的编译。另一方面,RegExp 对象 new RegExp('ab+c') 的构造函数导致正则表达式的运行时编译。

¥The literal notation results in compilation of the regular expression when the expression is evaluated. On the other hand, the constructor of the RegExp object, new RegExp('ab+c'), results in runtime compilation of the regular expression.

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

¥Use a string as the first argument to the RegExp() constructor when you want to build the regular expression from dynamic input.

构造函数中的标志

¥Flags in constructor

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

¥The expression new RegExp(/ab+c/, flags) will create a new RegExp using the source of the first parameter and the flags provided by the second.

使用构造函数时,需要正常的字符串转义规则(字符串中包含特殊字符时前面带有 \)。

¥When using the constructor function, the normal string escape rules (preceding special characters with \ when included in a string) are necessary.

例如,以下内容是等效的:

¥For example, the following are equivalent:

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

正则表达式的特殊处理

¥Special handling for regexes

注意:某物是否可以是 "regex",也可以是 duck-typed。它不一定是 RegExp

¥Note: Whether something is a "regex" can be duck-typed. It doesn't have to be a RegExp!

一些内置方法会特殊对待正则表达式。他们通过 多个步骤 来决定 x 是否是正则表达式:

¥Some built-in methods would treat regexes specially. They decide whether x is a regex through multiple steps:

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

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

¥Note that in most cases, it would go through the Symbol.match check, which means:

  • 一个实际的 RegExp 对象,其 Symbol.match 属性的值为 falsy 但不是 undefined(即使其他所有内容都完好无损,如 exec[Symbol.replace]()),可以像不是正则表达式一样使用。
  • 具有 Symbol.match 属性的非 RegExp 对象将被视为正则表达式。

做出此选择是因为 [Symbol.match]() 是最有指示性的属性,表明某些东西旨在用于匹配。(也可以使用 exec,但因为它不是符号属性,所以会有太多误报。)特别对待正则表达式的地方包括:

¥This choice was made because [Symbol.match]() is the most indicative property that something is intended to be used for matching. (exec could also be used, but because it's not a symbol property, there would be too many false positives.) The places that treat regexes specially include:

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

¥For example, String.prototype.endsWith() would coerce all inputs to strings, but it would throw if the argument is a regex, because it's only designed to match strings, and using a regex is likely a developer mistake.

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

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

¥You can get around the check by setting [Symbol.match] to a falsy value that's not undefined. This would mean that the regex cannot be used for String.prototype.match() (since without [Symbol.match], match() would construct a new RegExp object with the two enclosing slashes added by re.toString()), but it can be used for virtually everything else.

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 属性

¥Perl-like RegExp properties

请注意,一些 RegExp 属性既有长名称又有短名称(类似 Perl)。这两个名称始终指代相同的值。(Perl 是 JavaScript 为其正则表达式建模的编程语言。)另见 已弃用的 RegExp 属性

¥Note that several of the RegExp properties have both long and short (Perl-like) names. Both names always refer to the same value. (Perl is the programming language from which JavaScript modeled its regular expressions.) See also deprecated RegExp properties.

构造函数

¥Constructor

RegExp()

创建一个新的 RegExp 对象。

静态属性

¥Static properties

RegExp.$1, …, RegExp.$9 Deprecated

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

RegExp.input ($_) Deprecated

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

RegExp.lastMatch ($&) Deprecated

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

RegExp.lastParen ($+) Deprecated

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

RegExp.leftContext ($`) Deprecated

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

RegExp.rightContext ($') Deprecated

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

RegExp[Symbol.species]

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

实例属性

¥Instance properties

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

¥These properties are defined on RegExp.prototype and shared by all RegExp instances.

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 实例自己的属性。

¥These properties are own properties of each RegExp instance.

lastIndex

下一场比赛开始的索引。

实例方法

¥Instance methods

RegExp.prototype.compile() Deprecated

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

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]()

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

示例

¥Examples

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

¥Using a regular expression to change data format

以下脚本使用 String.prototype.replace() 方法来匹配格式为 First Last 的名称,并以 Last, First 格式输出。

¥The following script uses the String.prototype.replace() method to match a name in the format first last and output it in the format last, first.

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

¥In the replacement text, the script uses $1 and $2 to indicate the results of the corresponding matching parentheses in the regular expression pattern.

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

这将显示 "Cruz, Maria"

¥This displays "Cruz, Maria".

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

¥Using regular expression to split lines with different line endings/ends of line/line breaks

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

¥The default line ending varies depending on the platform (Unix, Windows, etc.). The line splitting provided in this example works on all platforms.

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

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

¥Note that the order of the patterns in the regular expression matters.

在多行上使用正则表达式

¥Using regular expression on multiple lines

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

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

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

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

¥Using a regular expression with the sticky flag

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

¥The sticky flag indicates that the regular expression performs sticky matching in the target string by attempting to match starting at 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)

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

¥The difference between the sticky flag and the global flag

使用粘性标志 y,下一场比赛必须发生在 lastIndex 位置,而使用全局标志 g,比赛可以发生在 lastIndex 位置或更晚的位置:

¥With the sticky flag y, the next match has to happen at the lastIndex position, while with the global flag g, the match can happen at the lastIndex position or later:

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 位。

¥With the global flag g, all 6 digits would be matched, not just 3.

正则表达式和 Unicode 字符

¥Regular expression and Unicode characters

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

¥\w and \W only matches ASCII based characters; for example, a to z, A to Z, 0 to 9, and _.

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

¥To match characters from other languages such as Cyrillic or Hebrew, use \uhhhh, where hhhh is the character's Unicode value in hexadecimal.

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

¥This example demonstrates how one can separate out Unicode characters from a word.

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(匹配任何语言的字母)等语句。

¥The Unicode property escapes feature provides a simpler way to target particular Unicode ranges, by allowing for statements like \p{scx=Cyrl} (to match any Cyrillic letter), or \p{L}/u (to match a letter from any language).

从 URL 中提取子域名

¥Extracting subdomain name from URL

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

注意:通常最好使用浏览器内置的 URL 解析器(通过使用 URL API.URL 解析器),而不是使用正则表达式来解析 URL。

¥Note: Instead of using regular expressions for parsing URLs, it is usually better to use the browsers built-in URL parser by using the URL API.

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

¥Building a regular expression from dynamic inputs

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']

规范

Specification
ECMAScript Language Specification
# sec-regexp-regular-expression-objects

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

Firefox 特定注释

¥Firefox-specific notes

从 Firefox 34 开始,如果捕获组的量词阻止其执行,则捕获组的匹配文本现在为 undefined 而不是空字符串:

¥Starting with Firefox 34, in the case of a capturing group with quantifiers preventing its exercise, the matched text for a capturing group is now undefined instead of an empty string:

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

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

¥Note that due to web compatibility, RegExp.$N will still return an empty string instead of undefined (bug 1053944).

也可以看看