我正在尝试编写一个正确拆分括号的表达式处理程序,直到今天它已经运行得很好,但我现在遇到了一个我没想过的问题。
我首先尝试用括号的内容拆分表达式,一旦这些被评估,我用结果和过程替换原始内容,直到没有括号为止。
表达式可能包含marcos / variables。宏用$ macro $。
包裹的文字表示一个典型的表达方式:
($exampleA$ * 3) + ($exampleB$ / 2)
在评估表达式之前替换宏,上面的工作正常,因为该过程如下:
用括号拆分表达式,这会产生两个表达式:
$exampleA$ * 3
$exampleB$ / 2
然后评估每个表达式,如果exampleA = 3且exampleB = 6:
$exampleA$ * 3 = 3 * 3 = 9
$exampleB$ / 2 = 6 / 2 = 3
然后使用结果重建表达式:
9 + 3
然后将没有任何括号的最终表达式计算为:
12
这样可以正常使用带有嵌套括号的表达式:
((($exampleA$ * 3) + ($exampleB$ / 2) * 2) - 1)
这完全打破了因为正在使用的正则表达式:
regex("(?<=\\()[^)]*(?=\\))");
结果:
($exampleA$ * 3
$exampleB$ / 2
那么如何正确解码呢,我希望将上述内容分解为:
$exampleA$ * 3
$exampleB$ / 2
答案 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)
将包含括号。
"\\(((?:\"\\(|\\)\"|[^()])+)\\)"
希望它有所帮助!