获取 JavaScript 正则表达式中每个捕获的索引

新手上路,请多包涵

我想匹配正则表达式 /(a).(b)(c.)d/"aabccde" ,并获取以下信息:

 "a" at index = 0
"b" at index = 2
"cc" at index = 3

我怎样才能做到这一点? String.match 返回匹配列表和完整匹配开始的索引,而不是每个捕获的索引。

编辑:一个不适用于普通 indexOf 的测试用例

regex: /(a).(.)/
string: "aaa"
expected result: "a" at 0, "a" at 2

注意:问题类似于 Javascript Regex: How to find index of each subexpression? ,但我无法修改正则表达式以使每个子表达式成为捕获组。

原文由 user1527166 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 897
1 个回答

目前有一个 建议(第 4 阶段)在本机 Javascript 中实现它:

ECMAScript 的 RegExp 匹配索引

ECMAScript RegExp Match Indices 提供有关捕获的子字符串的开始和结束索引相对于输入字符串开头的附加信息。

…我们建议在 --- 的数组结果( _子字符串数组_)上采用额外的 --- RegExp.prototype.exec() indices 属性。此属性本身是一个索引数组,其中包含每个捕获的子字符串的一对开始和结束索引。任何 不匹配 的捕获组将是 undefined ,类似于它们在 substrings 数组 中的对应元素。此外, indices 数组 本身会有一个 groups 属性,其中包含每个命名捕获组的开始和结束索引。

这是事情如何运作的一个例子。以下片段至少在 Chrome 中运行没有错误:

 const re1 = /a+(?<Z>z)?/d;

// indices are relative to start of the input string:
const s1 = "xaaaz";
const m1 = re1.exec(s1);
console.log(m1.indices[0][0]); // 1
console.log(m1.indices[0][1]); // 5
console.log(s1.slice(...m1.indices[0])); // "aaaz"

console.log(m1.indices[1][0]); // 4
console.log(m1.indices[1][1]); // 5
console.log(s1.slice(...m1.indices[1])); // "z"

console.log(m1.indices.groups["Z"][0]); // 4
console.log(m1.indices.groups["Z"][1]); // 5
console.log(s1.slice(...m1.indices.groups["Z"])); // "z"

// capture groups that are not matched return `undefined`:
const m2 = re1.exec("xaaay");
console.log(m2.indices[1]); // undefined
console.log(m2.indices.groups.Z); // undefined

因此,对于问题中的代码,我们可以这样做:

 const re = /(a).(b)(c.)d/d;
const str = 'aabccde';
const result = re.exec(str);
// indices[0], like result[0], describes the indices of the full match
const matchStart = result.indices[0][0];
result.forEach((matchedStr, i) => {
  const [startIndex, endIndex] = result.indices[i];
  console.log(`${matchedStr} from index ${startIndex} to ${endIndex} in the original string`);
  console.log(`From index ${startIndex - matchStart} to ${endIndex - matchStart} relative to the match start\n-----`);
});

输出:

 aabccd from index 0 to 6 in the original string
From index 0 to 6 relative to the match start
-----
a from index 0 to 1 in the original string
From index 0 to 1 relative to the match start
-----
b from index 2 to 3 in the original string
From index 2 to 3 relative to the match start
-----
cc from index 3 to 5 in the original string
From index 3 to 5 relative to the match start

请记住 indices 数组包含匹配组 相对于字符串开头 的索引,而不是相对于匹配开头的索引。


此处 提供了一个 polyfill。

原文由 CertainPerformance 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题