JavaScript RegExp

时间:2014-01-07 16:47:38

标签: javascript regex

我想要

Match 1: test(testing() tester())

Match 2: theTest()

test(testing() tester()) theTest()

我正在使用这个RegExp

/([a-z]+)\((.*)\)/ig

但它是否匹配整个字符串

我认为问题在于.*,但我无法弄清楚该怎么做

如何让RegExp与大括号相匹配而不与内部大括号相冲突

这是Example

编辑:由于我发现这对于我们正在寻找的东西并非完全可能,是否有一个功能或方法可以完成我想要的东西?

4 个答案:

答案 0 :(得分:2)

有趣的问题。是的,JavaScript正则表达式引擎确实无法匹配最外层平衡的匹配括号对,但它可以轻松匹配最里面的平衡对使用以下简单的正则表达式模式:

reInnerParens

/\([^()]*\)/

这种正则表达式可以以迭代的方式有效地使用,以从内到外匹配嵌套的平衡括号。以下有用的测试函数使用此方法来确定字符串是否具有平衡,可能嵌套到任何深度,匹配括号:

function isBalancedParens(text)

function isBalancedParens(text) {
    var reInnerParens = /\([^()]*\)/g;
    // Iteratively remove balanced pairs from inside out.
    while (text.search(reInnerParens) !== -1) {
        text = text.replace(reInnerParens, '');
    }
    // Any remaining parens indicate unbalanced pairs.
    if (/[()]/.test(text)) return false;
    return true;
}

上述函数通过从内到外迭代地移除最内部平衡括号来工作,直到没有更多匹配。如果有任何剩余的括号,则该字符串包含未匹配的括号,并且不平衡。

可以使用类似的迭代技术来解决手头的问题。首先,需要一个正则表达式,它匹配一对平衡的括号,这对括号至少包含一对内括号,但只嵌套一层深度。这是自由间隔模式格式:

reOuterParens

/* reOuterParens
    # Match outer parens having inner parens one level deep.
    \(          # Outer open paren.
    (           # $1: Contents of outer parens .
      (?:       # One or more nested parens (1 deep).
        [^()]*  # Zero or more non-parens.
        \(      # Inner open paren.
        [^()]*  # Zero or more non-parens.
        \)      # Inner close paren.
      )+        # One or more nested parens (1 deep).
      [^()]*    # Zero or more non-parens.
    )           # End $1: Contents of outer parens .
    \)          # Outer close paren.
*/
var reOuterParens = /\(((?:[^()]*\([^()]*\))+[^()]*)\)/g;

以下测试的JavaScript函数迭代地应用此正则表达式将所有内部括号“隐藏”为HTML实体。一旦完成,那么只剩下所需的最外面的括号。

function getOutermostParens(text)

// Match and return all outermost "word(..(..))" patterns from string.
function getOutermostParens(text) {
    var reOuterParens = /\(((?:[^()]*\([^()]*\))+[^()]*)\)/g;
    var results = [];
    // Ensure all (possibly nested) matching parentheses are properly balanced.
    if (!isBalancedParens(text)) return null;
    text = text.replace(/&/g, '&') // Temporarily hide html entities.
    // Iteratively hide all parens nested one level deep.
    while (text.search(reOuterParens) !== -1) {
        // Hide nested parens by converting to html entities.
        text = text.replace(reOuterParens,
            function(m0, m1){
                m1 = m1.replace(/[()]/g,
                    function(n0){
                        return {'(':'(', ')': ')'}[n0];
                    });
                return '('+ m1 +')';
            });
    }
    // Match all outermost "word(...)" and load into results array.
    text.replace(/\w+\([^()]*\)/g,
        function(m0){
            m0 = m0.replace(/&#4[01];/g, // Restore hidden parens.
                function(n0){
                    return {'(': '(', ')': ')'}[n0];
                });
            // Restore temporarily hidden html entities.
            m0 = m0.replace(/&/g, '&');
            results.push(m0);
            return ''; // Not used.
        });
    return results;
}

请注意,内部嵌套()括号字符是通过将它们替换为HTML实体等价物(即())来隐藏的,但为了安全地执行此操作,所有HTML实体都是可能存在于原始字符串中必须首先受到保护。这是通过在例程开头用&替换所有&来完成的,然后在例程结束时将其全部恢复。

答案 1 :(得分:1)

为什么不在最后一个空格上拆分字符串?

str.split(/ (?=[^ ]*$)/);

FIDDLE

答案 2 :(得分:-1)

    String i = "test(testing() tester()) theTest()";

    String regex = "\\w+\\(\\w+\\(\\)\\s\\w+\\(\\)\\)|\\w+\\(\\)";
    p = Pattern.compile(regex);
    m = p.matcher(i);
    if (m.find()) {
        System.out.println(m.group());
    }

尝试使用此正则表达式,如果您的文字只是这么多。

答案 3 :(得分:-1)

使用以下正则表达式:

/[a-z]+\(([a-z]+\(\) [a-z]+\(\))*\)/gi

完整代码:

str.match(/[a-z]+\(([a-z]+\(\) [a-z]+\(\))*\)/gi);

O / P:

["test(testing() tester())", "theTest()"]