使用“|”确定哪个子模式匹配正则表达式中的运算符

时间:2013-11-18 20:59:18

标签: javascript regex

我有一个正则表达式,它与一个'|',也就是OR运算符拼凑在一起,它由较小的子模式组成。我正在尝试确定哪个子模式匹配,但RegExp引擎只会给我整个表达式。

示例:

这是我编译的(近似的)拼凑表达式(为了理解而大量简化:

/^somestring-(\w+)$|^notherstring-(\d+)-(\w+)$|^laststring-(\w+)-([a-f])$/g

以下是输入文字:

laststring-eof

所以在我的匹配数组中,我看到一些带有“未定义值”的索引(因为之前有几个尝试过的匹配与整个表达式不匹配),但我得到了我的匹配“eof”。< / p>

这一切都很棒,给了我大部分我想要的东西。我得到的不是我需要的,就是知道匹配的子模式是“^ laststring - (\ w +)$”,或者至少知道这是第三个子模式主要表达。我不能依赖匹配数组的长度,因为每个子模式可以有无限数量的匹配组。

我尝试了regexp.lastIndex,但该属性只给出了子模式中的最后一个匹配,而不是整个表达式中子模式的偏移。

2 个答案:

答案 0 :(得分:1)

我不确定这是否可行,但我认为如果你在每个子组周围加上()括号,你应该能够检查表达式是否匹配时哪些是非空的,这样你就可以了可以看到哪种模式匹配。

在你的情况下,会创建3个额外的子组,如果我正确计算它会是这样的:

第一组=第一个子模式

第二组=第一个子模式中的第一个匹配组

第三组=第二个子模式

第四组和第五组=第二子模式中的子模式

第六=第三小组

所以你检查第一个,第三个和第六个匹配组,其中一个非空,这是你的匹配模式。

答案 1 :(得分:0)

知道哪个分支匹配的唯一方法是查看结果数组中存在哪些组:

s = "laststring-eof";
p = /^somestring-(\w+)$|^notherstring-(\d+)-(\w+)$|^laststring-(\w+)-([a-f])$/g;
m = p.exec(s);
if (m[1] !== undefined) { /* first branch */ }
else if (m[2] !== undefined) { /* second branch */ }
else if (m[4] !== undefined) { /* last branch */ }

当不同分支从其他模式拼凑在一起时,您需要计算每个分支中捕获组的数量:

function countCapturingGroups(regexp) {
    var count = 0;
    regexp.source.replace(/\[(?:\\.|[^\\\]])*\]|\\.|(\()(?!\?)/g,
        function (full, capturing) {
            if (capturing) count++;
        });
    return count;
}

对于没有捕获组的分支,您可以添加一个空捕获:

p = /^somestring-(\w+)$|()^nocaptures$/g;

如果不能保证包括第一组,也可以对其他分支进行。

更长的例子:

function MultiRegExp(patterns)
{
    this.patterns = patterns;
    this.combined = new RegExp(patterns.map(function (p) {
        return "()" + p.source;
    }).join("|"));
    this.numcaptures = patterns.map(countCapturingGroups);
    this.start = [1];
    for (var i = 1; i < numcaptures.length; i++) {
        this.start[i] = this.start[i-1] + this.numcaptures[i-1] + 1;
    }
}

MultiRegExp.prototype.exec = function (str) {
    var m = this.combined.exec(str);
    if (!m) return;
    for (var i = 0; i < this.numcaptures.length; i++) {
        var offset = this.start[i];
        if (m[offset] !== undefined) {
            var result = [i,m[0]];
            for (var j = 1; j <= this.numcaptures[i]; j++) {
                result.push(m[offset + j]);
            }
            return result;
        }
    }
};

var p = new MultiRegExp([
    /^somestring-(\w+)$/,
    /^notherstring-(\d+)-(\w+)$/,
    /^laststring-(\w+)-([a-f])$/,
    /^nocaptures$/
]);

p.exec("somestring-abc"); // -> [0, "somestring-abc", "abc"]
p.exec("nocaptures"); // -> [3, "nocaptures"]
相关问题