试一试
const regex = /fo+/g;
const str = "table football, foosball";
let array;
while ((array = regex.exec(str)) !== null) {
console.log(`Found ${array[0]}. Next starts at ${regex.lastIndex}.`);
// Expected output: "Found foo. Next starts at 9."
// Expected output: "Found foo. Next starts at 19."
}
语法
exec(str)
参数
返回值
如果匹配失败,exec() 方法返回 null,并将正则表达式的 lastIndex 设置为 0。
如果匹配成功,exec() 方法返回一个数组,并更新正则表达式对象的 lastIndex 属性。返回的数组将匹配的文本作为第一个元素,然后为匹配文本的每个捕获组提供一个元素。数组还具有以下附加属性:
index-
匹配在字符串中的 0 索引。
input-
用于匹配的原始字符串。
groups-
一个
null-prototype 对象,包含命名捕获组,其键是名称,值是捕获组,如果没有定义命名捕获组,则值为undefined。有关更多信息,请参阅 捕获组。 indices可选-
仅当设置了
d标志时,才会出现此属性。它是一个数组,其中每个条目代表一个子字符串匹配的边界。此数组中每个元素的索引对应于exec()返回的数组中相应子字符串匹配的索引。换句话说,第一个indices条目代表整个匹配,第二个indices条目代表第一个捕获组,依此类推。每个条目本身是一个包含两个元素的数组,第一个数字代表匹配的开始索引,第二个数字代表其结束索引。indices数组还额外有一个groups属性,其中包含所有命名捕获组的null-prototype 对象。键是捕获组的名称,每个值是一个包含两个元素的数组,第一个数字是开始索引,第二个数字是捕获组的结束索引。如果正则表达式不包含任何命名捕获组,则groups为undefined。
描述
当设置了 全局或 粘性 标志(例如,/foo/g 或 /foo/y)时,JavaScript RegExp 对象是有状态的。它们会存储上一次匹配的 lastIndex。通过内部使用此属性,exec() 可以用于迭代字符串中的多个匹配(带有捕获组),而不是像 String.prototype.match() 那样只获取匹配的字符串。
使用 exec() 时,如果设置了粘性标志,全局标志将不起作用——匹配始终是粘性的。
exec() 是正则表达式的原生方法。许多其他正则表达式方法在内部调用 exec() — 包括字符串方法调用的那些,例如 [Symbol.replace]()。虽然 exec() 本身功能强大(并且效率最高),但它通常不能最清晰地表达意图。
- 如果你只关心正则表达式是否匹配一个字符串,而不关心实际匹配了什么,请改用
RegExp.prototype.test()。 - 如果你正在查找全局正则表达式的所有匹配项,并且不关心捕获组等信息,请改用
String.prototype.match()。此外,String.prototype.matchAll()可以通过允许你迭代匹配项来简化匹配字符串的多个部分(带有捕获组)。 - 如果你执行匹配是为了在字符串中找到其索引位置,请改用
String.prototype.search()方法。
exec() 对于上面任何方法都难以实现的复杂操作很有用,通常在你需要手动调整 lastIndex 时。(String.prototype.matchAll() 会复制正则表达式,因此在迭代 matchAll 时更改 lastIndex 不会影响迭代。) 其中一个例子请参阅 重置 lastIndex。
示例
使用 exec()
考虑以下示例
// 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" |
index |
4 |
indices |
[[4, 25], [10, 15], [20, 25]]groups: { color: [10, 15 ]} |
input |
"The Quick Brown Fox Jumps Over The Lazy Dog" |
groups |
{ color: "Brown" } |
此外,re.lastIndex 将被设置为 25,因为这个正则表达式是全局的。
查找连续匹配项
如果你的正则表达式使用了 g 标志,你可以多次使用 exec() 方法在同一个字符串中查找连续的匹配项。这样做时,搜索将从正则表达式的 lastIndex 属性指定的 str 子字符串开始(test() 也会推进 lastIndex 属性)。请注意,在搜索不同字符串时,lastIndex 属性不会被重置,它将从其当前 lastIndex 开始搜索。
例如,假设你有以下脚本
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
警告: 有许多陷阱可能导致这种情况变成无限循环!
你通常可以用 String.prototype.matchAll() 替换此类代码,使其更不容易出错。
使用 exec() 和 RegExp 字面量
你也可以在不显式创建 RegExp 对象的情况下使用 exec()
const matches = /(hello \S+)/.exec("This is a hello world!");
console.log(matches[1]);
这将记录一条包含 'hello world!' 的消息。
规范
| 规范 |
|---|
| ECMAScript® 2026 语言规范 # sec-regexp.prototype.exec |
浏览器兼容性
加载中…