获得每个捕获指数在JavaScript正则表达式(Get index of each capture

2019-08-21 11:39发布

我想匹配像一个正则表达式/(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正则表达式:如何找到每个子表达式的指数? ,但我不能修改正则表达式使每个子表达式捕获组。

Answer 1:

所以,你有一个文本和正则表达式:

txt = "aabccde";
re = /(a).(b)(c.)d/;

第一步是获得匹配的正则表达式的子串的名单:

subs = re.exec(txt);

然后,你可以做的文本为每串一个简单的搜索。 你必须保持在一个变量的最后一个子的位置。 我命名这个变量cursor

var cursor = subs.index;
for (var i = 1; i < subs.length; i++){
    sub = subs[i];
    index = txt.indexOf(sub, cursor);
    cursor = index + sub.length;


    console.log(sub + ' at index ' + index);
}

编辑:感谢@nhahtdh,我已经提高了mecanism,并提出了完整的功能:

String.prototype.matchIndex = function(re){
    var res  = [];
    var subs = this.match(re);

    for (var cursor = subs.index, l = subs.length, i = 1; i < l; i++){
        var index = cursor;

        if (i+1 !== l && subs[i] !== subs[i+1]) {
            nextIndex = this.indexOf(subs[i+1], cursor);
            while (true) {
                currentIndex = this.indexOf(subs[i], index);
                if (currentIndex !== -1 && currentIndex <= nextIndex)
                    index = currentIndex + 1;
                else
                    break;
            }
            index--;
        } else {
            index = this.indexOf(subs[i], cursor);
        }
        cursor = index + subs[i].length;

        res.push([subs[i], index]);
    }
    return res;
}


console.log("aabccde".matchIndex(/(a).(b)(c.)d/));
// [ [ 'a', 1 ], [ 'b', 2 ], [ 'cc', 3 ] ]

console.log("aaa".matchIndex(/(a).(.)/));
// [ [ 'a', 0 ], [ 'a', 1 ] ] <-- problem here

console.log("bababaaaaa".matchIndex(/(ba)+.(a*)/));
// [ [ 'ba', 4 ], [ 'aaa', 6 ] ]


Answer 2:

我写MultiRegExp这个前一阵子。 只要你没有嵌套的捕捉组,它应该做的伎俩。 它通过将这些捕获之间群体的正则表达式,并使用所有的中间群体,计算所要求的组位置。

var exp = new MultiRegExp(/(a).(b)(c.)d/);
exp.exec("aabccde");

应该返回

{0: {index:0, text:'a'}, 1: {index:2, text:'b'}, 2: {index:3, text:'cc'}}

真人版



Answer 3:

我创建了一个小的正则表达式解析器也能解析嵌套组就像一个魅力。 这是小,但巨大的。 不完全是。 像多纳尔兹手。 我是真的很高兴,如果有人能对其进行测试,所以这将是战斗测试。 :它可以在这里找到https://github.com/valorize/MultiRegExp2

用法:

let regex = /a(?: )bc(def(ghi)xyz)/g;
let regex2 = new MultiRegExp2(regex);

let matches = regex2.execForAllGroups('ababa bcdefghixyzXXXX'));

Will output:
[ { match: 'defghixyz', start: 8, end: 17 },
  { match: 'ghi', start: 11, end: 14 } ]


Answer 4:

基于在ECMA正则表达式语法我写了一个解析器相应的解决了这个之外的问题(全索引exec方法)以及JavaScript的正则表达式执行例如其他限制RegExp类的扩展:集团基于搜索和替换。 您可以测试,请下载执行 (是也可作为NPM模块)。

实现原理如下(小例子):

//Retrieve content and position of: opening-, closing tags and body content for: non-nested html-tags.
var pattern = '(<([^ >]+)[^>]*>)([^<]*)(<\\/\\2>)';
var str = '<html><code class="html plain">first</code><div class="content">second</div></html>';
var regex = new Regex(pattern, 'g');
var result = regex.exec(str);

console.log(5 === result.length);
console.log('<code class="html plain">first</code>'=== result[0]);
console.log('<code class="html plain">'=== result[1]);
console.log('first'=== result[3]);
console.log('</code>'=== result[4]);
console.log(5=== result.index.length);
console.log(6=== result.index[0]);
console.log(6=== result.index[1]);
console.log(31=== result.index[3]);
console.log(36=== result.index[4]);

我试图以及执行从@velop但执行似乎车例如它不能正确例如处理反向引用“/一个(?:)BC(DEF(\ 1 GHI)XYZ)/ G” -在前面添加paranthesis时则反向引用\ 1需要被相应地增加(这是不是在他的实施的情况下)。



Answer 5:

随着RegExp.prototype.exec()和搜索结果的正确指标:

let regex1 = /([a-z]+):([0-9]+)/g;
let str1 = 'hello:123';
let array1;
let resultArray = []

while ((array1 = regex1.exec(str1)) !== null) {
  const quantityFound = (Object.keys(array1).length - 3); // 3 default keys
  for (var i = 1; i<quantityFound; i++) { // start in 1 to avoid the complete found result 'hello:123'
    const found = array1[i];
    arraySingleResult = [found, str1.indexOf(found)];
    resultArray.push(arraySingleResult);
  }
}
console.log('result:', JSON.stringify(resultArray));


Answer 6:

我不完全相信你的要求是什么进行搜索,但这里是你如何能得到你的第一个例子中使用所需的输出Regex.exec()和while循环。

JavaScript的

var myRe = /^a|b|c./g;
var str = "aabccde";
var myArray;
while ((myArray = myRe.exec(str)) !== null)
{
  var msg = '"' + myArray[0] + '" ';
  msg += "at index = " + (myRe.lastIndex - myArray[0].length);
  console.log(msg);
}

产量

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

使用lastIndex属性,你可以减去当前匹配的字符串的长度,以获得起始索引。



文章来源: Get index of each capture in a JavaScript regex