RegExp.prototype.exec()

基线 广泛可用

此功能已得到良好建立,并在许多设备和浏览器版本上都能正常工作。它从以下时间起在所有浏览器中都可用: 2015 年 7 月.

exec() 方法是 RegExp 实例的方法,它使用此正则表达式在指定字符串中执行搜索以进行匹配,并返回结果数组或 null

试一试

语法

js
exec(str)

参数

str

要与正则表达式匹配的字符串。所有值都将 强制转换为字符串,因此省略它或传递 undefined 会导致 exec() 搜索字符串 "undefined",这很少是你想要的。

返回值

如果匹配失败,exec() 方法将返回 null,并将正则表达式的 lastIndex 设置为 0

如果匹配成功,exec() 方法将返回一个数组,并更新正则表达式对象的 lastIndex 属性。返回的数组将匹配的文本作为第一个项目,然后为匹配文本的每个捕获组添加一个项目。该数组还具有以下其他属性

索引

匹配在字符串中的 0 为基的索引。

输入

与之匹配的原始字符串。

命名捕获组的 null 原型对象,其键是名称,值是捕获组,或 undefined(如果未定义任何命名捕获组)。有关更多信息,请参阅 捕获组

indices 可选

此属性仅在设置了 d 标志时存在。它是一个数组,其中每个条目都表示子字符串匹配的边界。此数组中每个元素的索引对应于 exec() 返回的数组中相应的子字符串匹配的索引。换句话说,第一个 indices 条目表示整个匹配,第二个 indices 条目表示第一个捕获组,等等。每个条目本身都是一个包含两个元素的数组,其中第一个数字表示匹配的开始索引,第二个数字表示匹配的结束索引。

indices 数组还具有一个 groups 属性,该属性保存所有命名捕获组的 null 原型对象。键是捕获组的名称,每个值都是一个包含两个元素的数组,第一个数字是捕获组的开始索引,第二个数字是捕获组的结束索引。如果正则表达式不包含任何命名捕获组,则 groupsundefined

描述

当 JavaScript RegExp 对象设置了 全局粘性 标志时(例如 /foo/g/foo/y),它们是有状态的。它们存储来自先前匹配的 lastIndex。在内部使用它,exec() 可用于迭代文本字符串中的多个匹配项(使用捕获组),而不是仅使用 String.prototype.match() 获取匹配的字符串。

在使用 exec() 时,当设置粘性标志时,全局标志没有影响 - 匹配始终是粘性的。

exec() 是正则表达式的基本方法。许多其他正则表达式方法在内部调用 exec() - 包括由字符串方法调用的那些方法,例如 [Symbol.replace]()。虽然 exec() 本身功能强大(而且效率最高),但它通常不能最清楚地传达意图。

  • 如果您只关心正则表达式是否与字符串匹配,但不关心实际匹配的内容,请使用 RegExp.prototype.test()
  • 如果您正在查找全局正则表达式的所有出现情况,并且不关心捕获组等信息,请使用 String.prototype.match()。此外,String.prototype.matchAll() 通过允许您迭代匹配项来简化匹配字符串的多个部分(使用捕获组)。
  • 如果您正在执行匹配以查找其在字符串中的索引位置,请使用 String.prototype.search() 方法。

示例

使用 exec()

请考虑以下示例

js
// Match "quick brown" followed by "jumps", ignoring characters in between
// Remember "brown" and "jumps"
// Ignore case
const re = /quick\s(?<color>brown).+?(jumps)/dgi;
const result = re.exec("The Quick Brown Fox Jumps Over The Lazy Dog");

下表显示了在运行此脚本后 result 的状态

属性
[0] "Quick Brown Fox Jumps"
[1] "Brown"
[2] "Jumps"
索引 4
索引 [[4, 25], [10, 15], [20, 25]]
组:{ color: [10, 15 ]}
输入 "The Quick Brown Fox Jumps Over The Lazy Dog"
{ color: "brown" }

此外,由于此正则表达式是全局的,re.lastIndex 将被设置为 25

查找连续匹配项

如果您的正则表达式使用 g 标志,则可以使用 exec() 方法多次在同一字符串中查找连续匹配项。当您这样做时,搜索将从正则表达式 lastIndex 属性指定的 str 子字符串开始 (test() 也将推进 lastIndex 属性)。请注意,当搜索不同的字符串时,lastIndex 属性不会重置,它将从其现有的 lastIndex 开始搜索。

例如,假设您有以下脚本

js
const myRe = /ab*/g;
const str = "abbcdefabh";
let myArray;
while ((myArray = myRe.exec(str)) !== null) {
  let msg = `Found ${myArray[0]}. `;
  msg += `Next match starts at ${myRe.lastIndex}`;
  console.log(msg);
}

此脚本将显示以下文本

Found abb. Next match starts at 3
Found ab. Next match starts at 9

警告: 有很多陷阱会导致这成为一个无限循环!

  • 不要将正则表达式字面量(或 RegExp 构造函数)放在 while 条件中——它将在每次迭代时重新创建正则表达式并重置 lastIndex
  • 确保 全局 (g) 标志 已设置,否则 lastIndex 永远不会被推进。
  • 如果正则表达式可能匹配零长度字符(例如 /^/gm),请在每次迭代时手动增加其 lastIndex,以避免停留在同一个位置。

您通常可以用 String.prototype.matchAll() 替换此类代码,以使其不易出错。

使用带有正则表达式字面量的 exec()

您也可以使用 exec(),而无需显式创建 RegExp 对象

js
const matches = /(hello \S+)/.exec("This is a hello world!");
console.log(matches[1]);

这将记录包含 'hello world!' 的消息。

规范

规范
ECMAScript 语言规范
# sec-regexp.prototype.exec

浏览器兼容性

BCD 表仅在浏览器中加载

另请参阅