我试图创建一个正则表达式,它将捕获第一组中没有括号括起来的字符串,后跟括号括起来的任意数量的字符串。
e.g。
2(3)(4)(5)
应该是:2 - 第一组,第3组,依此类推。
我想出的是这个正则表达式:(我使用的是JavaScript)
([^()]*)(?:\((([^)]*))\))*
然而,当我输入像A(B)(C)(D)这样的字符串时,我只会捕获A和D.
https://regex101.com/r/HQC0ib/1
有谁可以帮我解决这个问题,并可能解释错误的位置?
答案 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]+
- 除(
,)
和空白(?:\([^)]*\))*
- 0个或更多序列:
\(
- (
[^)]*
- 除)
\)
- )
分割正则表达式[()]+
匹配1个或多个)
或(
个字符,filter(Boolean)
删除空项。