我有一个正则表达式,它与一个'|',也就是OR运算符拼凑在一起,它由较小的子模式组成。我正在尝试确定哪个子模式匹配,但RegExp引擎只会给我整个表达式。
示例:
这是我编译的(近似的)拼凑表达式(为了理解而大量简化:
/^somestring-(\w+)$|^notherstring-(\d+)-(\w+)$|^laststring-(\w+)-([a-f])$/g
以下是输入文字:
laststring-eof
所以在我的匹配数组中,我看到一些带有“未定义值”的索引(因为之前有几个尝试过的匹配与整个表达式不匹配),但我得到了我的匹配“eof”。< / p>
这一切都很棒,给了我大部分我想要的东西。我得到的不是我需要的,就是知道匹配的子模式是“^ laststring - (\ w +)$”,或者至少知道这是第三个子模式主要表达。我不能依赖匹配数组的长度,因为每个子模式可以有无限数量的匹配组。
我尝试了regexp.lastIndex,但该属性只给出了子模式中的最后一个匹配,而不是整个表达式中子模式的偏移。
答案 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"]