为什么这个组没有捕获括号中出现的所有项目?

时间:2017-07-15 09:39:29

标签: javascript regex

我试图创建一个正则表达式,它将捕获第一组中没有括号括起来的字符串,后跟括号括起来的任意数量的字符串。

e.g。

2(3)(4)(5)

应该是:2 - 第一组,第3组,依此类推。

我想出的是这个正则表达式:(我使用的是JavaScript)

([^()]*)(?:\((([^)]*))\))*

然而,当我输入像A(B)(C)(D)这样的字符串时,我只会捕获A和D.

https://regex101.com/r/HQC0ib/1

有谁可以帮我解决这个问题,并可能解释错误的位置?

3 个答案:

答案 0 :(得分:1)

您不能拥有未确定数量的捕获组。您获得的捕获组数由正则表达式决定,而不是由它解析的输入决定。在另一次重复中发生的捕获组实际上只会保留最后一次重复。

如果你知道你可以遇到的最大重复次数,那么只需重复多次模式,并使用?使每个模式可选。例如,这将在括号内捕获最多4个项目:

([^()]*)(?:\(([^)]*)\))?(?:\(([^)]*)\))?(?:\(([^)]*)\))?(?:\(([^)]*)\))?

答案 1 :(得分:1)

这不是错误。正是在正则表达式中,当您重复捕获组(...)*时,只会将最后一次出现在反向引用中。

例如:

在字符串“a,b,c,d”上,如果匹配/(,[a-z])+/,则捕获组1(\1)的后向引用将给出“,d”。

如果您希望它返回更多,那么您可以将其包围在另一个捕获组中 - >使用/((?:,[a-z])+)/\1将提供“,b,c,d”。

要在括号之间获取这些数字,您也可以尝试匹配单词字符。

例如:

var str = "2(3)(14)(B)";
var matches = str.match(/\w+/g);

console.log(matches);

答案 2 :(得分:1)

由于您无法在JS regex中使用\G锚点(以匹配连续匹配),并且在.NET / PyPi正则表达式库中没有每个捕获组的堆栈,因此您需要使用2步方法:1)将字符串匹配为整个文本条纹,然后2)后处理以获得所需的值。



var s = "2(3)(4)(5) A(B)(C)(D)";
var rx = /[^()\s]+(?:\([^)]*\))*/g;
var res = [], m;
while(m=rx.exec(s)) {
  res.push(m[0].split(/[()]+/).filter(Boolean));
}
console.log(res);




我将\s添加到否定字符类[^()],因为我将这些示例添加为单个字符串。

模式详情

  • [^()\s]+ - 除()和空白
  • 以外的1个或多个字符
  • (?:\([^)]*\))* - 0个或更多序列:
    • \( - (
    • [^)]* - 除)
    • 以外的0个字符
    • \) - )

分割正则表达式[()]+匹配1个或多个)(个字符,filter(Boolean)删除空项。