Javascript 确定在使用'|';正则表达式中的运算符
我有一个正则表达式,它是由一个“|”、aka或操作符拼凑而成的,它由更小的子模式组成。我试图确定匹配了哪个子模式,但是RegExp引擎只会给我整个表达式 示例: 以下是我的编译(近似)分段表达式(为了理解,进行了大量简化:Javascript 确定在使用'|';正则表达式中的运算符,javascript,regex,Javascript,Regex,我有一个正则表达式,它是由一个“|”、aka或操作符拼凑而成的,它由更小的子模式组成。我试图确定匹配了哪个子模式,但是RegExp引擎只会给我整个表达式 示例: 以下是我的编译(近似)分段表达式(为了理解,进行了大量简化: /^somestring-(\w+)$|^notherstring-(\d+)-(\w+)$|^laststring-(\w+)-([a-f])$/g 以下是输入文本: laststring-eof 因此,在我的matches数组中,我看到了一些带有“未定义值”的索引(因
/^somestring-(\w+)$|^notherstring-(\d+)-(\w+)$|^laststring-(\w+)-([a-f])$/g
以下是输入文本:
laststring-eof
因此,在我的matches数组中,我看到了一些带有“未定义值”的索引(因为之前有几个尝试的匹配与整个表达式不匹配),但我也得到了匹配“eof”
这一切都很好,给了我大部分我想要的。我没有得到我需要的,是知道匹配的子模式是“^laststring-(\w+)$”,或者至少,知道这是主表达式中的第三个子模式。我不能依赖匹配数组的长度,因为每个子模式可以有无限多个匹配组
我尝试了regexp.lastIndex,但该属性只提供子模式中的最后一个匹配项,而不是整个表达式中子模式的偏移量。我不确定这是否可行,但我认为如果您将()在每个子组周围的括号中,如果表达式匹配,您应该能够检查其中哪些是非空的,这样您就可以看到哪些模式匹配 在您的情况下,这将创建3个额外的子组,如果我计算正确,它将如下所示: 第一组=第一个子模式 第二组=第一子模式中的第一个匹配组 第三组=第二个子模式 第四组和第五组=第二个子模式中的子模式 第六组=第三分组
因此,您可以检查第一个、第三个和第六个匹配组,其中一个组为非空,这是您的匹配模式。了解哪个分支匹配的唯一方法是查看结果数组中存在哪些组:
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"]
函数MultiRegExp(模式)
{
这个模式=模式;
this.combined=newregexp(patterns.map)(函数(p){
返回“()”+p.source;
}).加入(“|”);
this.numcaptures=patterns.map(countCapturingGroups);
this.start=[1];
对于(变量i=1;i我怀疑您需要为3个不同的regexs@rpaskett首先修复不平衡的括号对
()
你不能简单地查看捕获的匹配来确定这一点(即它是否以somestring
,notherstring
,等等开始)?OP说这个例子“大大简化了”我目前正在进行3种不同的正则表达式匹配(在本例中),但正如我所提到的,子模式的数量是不确定的,最终可能是100+。我想在较小的正则表达式上进行100次匹配比匹配一个更大的表达式要慢。我可能是错的,但我仍然想知道如何完成我提出的任务。我实际上走了这条路,而且是确定的这是一种可能性,但我不能完全正确地理解。当每个子模式返回的匹配数不同时,会变得很混乱。如果你有一个例子,请分享。我的想法更多的是,你总是知道哪个匹配组对应于你搜索的子模式,但我不确定我是否正确理解了你的问题这有一个问题。我想如果你构造正则表达式,你总是可以计算你放入的匹配组的数量,看看哪些组对应于整个模式。然后你可以测试每个组是否匹配。我不确定为什么子模式返回的匹配数是个问题。所以我的意思是ke,有了matcher,调用matcher.matches(),然后检查是否(matcher.group(第一子模式的索引)!=null)如果子模式匹配。我不确定为什么返回的子模式数量会使这变得困难。或者知道子模式组的索引有问题吗?我认为问题在于组是基于左括号位置以平铺方式编号的,因此您无法知道没有k的第二个顶级组的编号现在知道第一个顶级组有多少个子组。大概,OP是将一些非文字的备选方案连接在一起,不想扫描每个备选方案,包括括号。但我真的认为从技术上讲,没有真正的备选方案。我想这将有助于了解更多关于他如何生成整个模式的信息。应该总是有一些方法来计算有多少子组,在最坏的情况下,我认为他可以将整个模式构造为一个字符串,然后在构造模式后搜索中间有多少子组。这是行不通的,因为它假设每个子模式都有精确的匹配数,如示例所示。模式会根据某些情况而变化。这也可能是:/^new-somestring-(\w+)-(\D{2})-(\D)$|^oldstring-(\D+)-(\w+)$| ^examplestring-(\w+)$/g@rpaskettexamp