用于括号的正则表达式(JavaScript)

时间:2013-08-22 00:03:56

标签: regex

这是我到目前为止创建的正则表达式: \((.+?)\)

这是我的测试字符串:(2+2) + (2+3*(2+3))

我得到的比赛是:

(2+2)(2+3*(2+3)

我希望我的比赛是:

(2+2)(2+3*(2+3))

我应该如何修改正则表达式?

2 个答案:

答案 0 :(得分:4)

您无法使用正则表达式解析parentesized表达式。 有一个数学证明,正则表达式不能这样做。 带括号的表达式是一种无上下文的语法,因此可以通过下推自动机(堆栈机器)识别。

无论如何,您可以定义一个正则表达式,该表达式适用于任何小于N个括号的表达式,具有任意有限N(即使表达式会变得复杂)。 您只需要确认您的括号可能包含另外任意数量的parenteses。

\(([^()]+(\([^)]+\)[^)]*)*)\)

它的工作原理如下:

  1. \(([^()]+匹配一个左括号,而不是括号;
  2. (\([^)]+\)[^)]*)*可选地,可能存在另一个由开括号形成的组,其中包含一些内容,然后是匹配的右括号。其他一些非括号字符可能会跟随。这可以重复任意次数。无论如何,最后必须有
  3. )\)另一个封闭的括号,与第一个匹配。
  4. 这应该适用于嵌套深度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)

在没有正则表达式帮助的情况下使用循环自己解析它怎么样? 这是一个简单的方法:

  • 你必须有一个变量,比如“level”,它记录到目前为止你遇到过多少个开括号(用0初始化它)。
  • 您还需要一个字符串缓冲区来包含每个匹配项(例如(2 + 2)或(2 + 3 *(2 + 3)))。
  • 最后,你需要在任何地方,只要你读完一个匹配就可以将缓冲区的内容转储。

  • 当你逐个字符地阅读字符串时,当你遇到“(”时,你会将等级增加1,当你遇到时减少1)“。然后,您可以将该字符放入缓冲区。

  • 当你遇到“)”并且等级恰好达到0时,那就是当你知道你有匹配时。这是您要转储缓冲区的内容并继续。

此方法假设每当输入字符串中有“(”,将始终存在对应的“)”时。此方法将处理任意数量的括号。