这是我到目前为止创建的正则表达式:
\((.+?)\)
这是我的测试字符串:(2+2) + (2+3*(2+3))
我得到的比赛是:
(2+2)
和
(2+3*(2+3)
我希望我的比赛是:
(2+2)
和
(2+3*(2+3))
我应该如何修改正则表达式?
答案 0 :(得分:4)
您无法使用正则表达式解析parentesized表达式。 有一个数学证明,正则表达式不能这样做。 带括号的表达式是一种无上下文的语法,因此可以通过下推自动机(堆栈机器)识别。
无论如何,您可以定义一个正则表达式,该表达式适用于任何小于N个括号的表达式,具有任意有限N(即使表达式会变得复杂)。 您只需要确认您的括号可能包含另外任意数量的parenteses。
\(([^()]+(\([^)]+\)[^)]*)*)\)
它的工作原理如下:
\(([^()]+
匹配一个左括号,而不是括号; (\([^)]+\)[^)]*)*
可选地,可能存在另一个由开括号形成的组,其中包含一些内容,然后是匹配的右括号。其他一些非括号字符可能会跟随。这可以重复任意次数。无论如何,最后必须有)\)
另一个封闭的括号,与第一个匹配。这应该适用于嵌套深度2.如果你想要嵌套深度3,你必须进一步递归,允许我在第(2)点描述的每个组都有一个嵌套的括号组。
如果使用堆栈,事情会变得容易多了。如:
foundMatches = [];
mStack = [];
start = RegExp("\\(");
mid = RegExp("[^()]*[()]?");
idx = 0;
while ((idx = input.search(start.substr(idx))) != -1) {
mStack.push(idx);
//Start a search
nidx = input.substr(idx + 1).search(mid);
while (nidx != -1 && idx + nidx < input.length) {
idx += nidx;
match = input.substr(idx).match(mid);
match = match[0].substr(-1);
if (match == "(") {
mStack.push(idx);
} else if (mStack.length == 1) {
break;
}
nidx = input.substr(idx + 1).search(mid);
}
//Check the result
if (nidx != -1 && idx + nidx < input.length) {
//idx+nidx is the index of the last ")"
idx += nidx;
//The stack contains the index of the first "("
startIdx = mStack.pop();
foundMatches.push(input.substr(startIdx, idx + 1 - startIdx));
}
idx += 1;
}
答案 1 :(得分:1)
在没有正则表达式帮助的情况下使用循环自己解析它怎么样? 这是一个简单的方法:
最后,你需要在任何地方,只要你读完一个匹配就可以将缓冲区的内容转储。
当你逐个字符地阅读字符串时,当你遇到“(”时,你会将等级增加1,当你遇到时减少1)“。然后,您可以将该字符放入缓冲区。
此方法假设每当输入字符串中有“(”,将始终存在对应的“)”时。此方法将处理任意数量的括号。