如何正确拆分包含括号的表达式

时间:2016-05-10 13:23:46

标签: regex

我正在尝试编写一个正确拆分括号的表达式处理程序,直到今天它已经运行得很好,但我现在遇到了一个我没想过的问题。

我首先尝试用括号的内容拆分表达式,一旦这些被评估,我用结果和过程替换原始内容,直到没有括号为止。

表达式可能包含marcos / variables。宏用$ macro $。

包裹的文字表示

一个典型的表达方式:

    ($exampleA$ * 3) + ($exampleB$ / 2)

在评估表达式之前替换宏,上面的工作正常,因为该过程如下:

  1. 用括号拆分表达式,这会产生两个表达式:

    $exampleA$ * 3
    $exampleB$ / 2
    
  2. 然后评估每个表达式,如果exam​​pleA = 3且exampleB = 6:

    $exampleA$ * 3 = 3 * 3 = 9
    $exampleB$ / 2 = 6 / 2 = 3
    
  3. 然后使用结果重建表达式:

    9 + 3
    
  4. 然后将没有任何括号的最终表达式计算为:

    12
    
  5. 这样可以正常使用带有嵌套括号的表达式:

        ((($exampleA$ * 3) + ($exampleB$ / 2) * 2) - 1)
    

    这完全打破了因为正在使用的正则表达式:

        regex("(?<=\\()[^)]*(?=\\))");
    

    结果:

        ($exampleA$ * 3
        $exampleB$ / 2
    

    那么如何正确解码呢,我希望将上述内容分解为:

        $exampleA$ * 3
        $exampleB$ / 2
    

4 个答案:

答案 0 :(得分:1)

传统的正则表达式无法处理嵌套括号等递归结构。

根据您使用的正则表达式风格,您可以使用regex recursion。否则,您可能需要一种新方法来解析组。我认为传统的方法是将表达式表示为一个堆栈:从一个空堆栈开始,当你找到一个&#39;(&#39;,当你找到&#39;时弹出)&#39;。

答案 1 :(得分:1)

你无法用正则表达式做到这一点。你真的需要一个递归方法,如下所示:

using System;
using System.Data;
using System.Xml;

public class Program
{
    public static void Main() {         

        Console.WriteLine(EvaluateExpression("(1 + 2) * 7"));           

    }


    public static int EvaluateExpression(string expression) {

        // Recursively evaluate parentheses as sub expressions
        var expr = expression.ToLower();
        while (expr.Contains("(")) {

            // Find first opening bracket
            var count = 1;
            var pStart = expr.IndexOf("(", StringComparison.InvariantCultureIgnoreCase);
            var pos = pStart + 1;

            // Find matching closing bracket
            while (pos < expr.Length && count > 0) {
                if (expr.Substring(pos, 1) == "(") count++;
                if (expr.Substring(pos, 1) == ")") count--;
                pos++;
            }

            // Error if no matching closing bracket
            if (count > 0) throw new InvalidOperationException("Closing parentheses not found.");

            // Divide expression into sub expression
            var pre = expr.Substring(0, pStart);
            var subexpr = expr.Substring(pStart + 1, pos - pStart - 2);
            var post = expr.Substring(pos, expr.Length - pos);

            // Recursively evaluate the sub expression
            expr = string.Format("{0} {1} {2}", pre, EvaluateExpression(subexpr), post);

        }

        // Replace this line with you're own logic to evaluate 'expr', a sub expression with any brackets removed.
        return (int)new DataTable().Compute(expr, null);

    }

}

我假设您在这里使用C#...但您应该明白这一点,并能够将其转化为任何内容。

答案 2 :(得分:1)

我不确定你要做什么。如果你想匹配最里面的表达式,这不会有帮助吗?:

regex("(?<=\\()[^()]*(?=\\))");

顺便说一句,你的例子中的括号是否有目的不平衡?

答案 3 :(得分:0)

如果您使用以下正则表达式,则可以将其捕获为group(1)group(0)将包含括号。

"\\(((?:\"\\(|\\)\"|[^()])+)\\)"

希望它有所帮助!