用于嵌套函数的 C# RegEx
C# RegEx for nested function
我在使用 C# 中的 RegEx 计算以下表达式时遇到问题。
add(1, 2, sub(4, add(1, 2)), div(4, 2))
下面将进行评估。
=> add(1, 2, sub(4, 3), 2)
=> add(1, 2, 1, 2)
=> 6
函数是从正则表达式中提取的,参数是任意数字。提前致谢。
这是我正在尝试的:
class Program
{
static Regex extractFuncRegex = new Regex(@"(?<func>add|sub|div)\s*\((?<params>.*)\)$", RegexOptions.ExplicitCapture);
static Regex extractArgsRegex = new Regex(@"([^,]+\(.+?\))|([^,]+)");
static void Main(string[] args)
{
string test = @"add(1, 2, sub(4, add(1, 2)), div(4, 2))";
Console.WriteLine(ParseFunction(test));
Console.ReadLine();
}
static string ParseFunction(string expr)
{
expr = extractFuncRegex.Replace(expr, (m) =>
{
string func = m.Groups["func"].Value;
string param = m.Groups["params"].Value;
Console.WriteLine("Function: {0}", func);
MatchCollection paramCollection = extractArgsRegex.Matches(param);
List<string> pa = new List<string>();
foreach (Match item in paramCollection)
{
string p = item.Groups[0].Value.Trim();
Console.WriteLine("\tParameter: {0}", p);
if (extractFuncRegex.IsMatch(p))
p = ParseFunction(p);
pa.Add(p);
}
switch (func)
{
case "add":
float a1 = 0;
foreach (string item in pa)
a1 += float.Parse(item);
return a1.ToString();
case "sub":
return (float.Parse(pa[0]) - float.Parse(pa[1])).ToString();
case "div":
return (float.Parse(pa[0]) / float.Parse(pa[1])).ToString();
default:
return expr;
}
});
return expr;
}
}
调试的话可以看到,解析有问题
sub(4, add(1, 2))
到目前为止,您显然在这方面做得很好,所以我不会说 "don't use regular expressions, throw it away and use something else" - 我将展示如何通过最少的更改使您的代码正常工作。
首先,将您的 extractFuncRegex
更改为
@"(?<func>add|sub|div)\s*\((?<params>[^()]*)\)"
我已将 params
组中的 .*
替换为 [^()]*
。这意味着它只会匹配 不包含任何其他函数调用 的函数调用 - 因为这是我们唯一可以直接处理的事情。我还删除了尾随 $
以使其正常工作。
现在的诀窍是调用 ParseFunction
或 extractFuncRegex.Replace
直到 没有替换 。例如,您可以像这样将对 extractFuncRegex.Replace
的调用置于循环中(未经测试):
bool doneWork = true;
while (doneWork)
{
doneWork = false;
expr = extractFuncRegex.Replace(expr, (m) =>
{
doneWork = true;
...
});
}
...
使用这个,你会得到一系列逐渐简化的表达式。在每个阶段,只有最深个函数调用被替换。
add(1, 2, sub(4, add(1, 2)), div(4, 2))
|-------- |--------
add(1, 2, sub(4, 3 ), 2 )
|----------------
add(1, 2, 1 , 2 )
|--------------------------------------
6
我在使用 C# 中的 RegEx 计算以下表达式时遇到问题。
add(1, 2, sub(4, add(1, 2)), div(4, 2))
下面将进行评估。
=> add(1, 2, sub(4, 3), 2)
=> add(1, 2, 1, 2)
=> 6
函数是从正则表达式中提取的,参数是任意数字。提前致谢。
这是我正在尝试的:
class Program
{
static Regex extractFuncRegex = new Regex(@"(?<func>add|sub|div)\s*\((?<params>.*)\)$", RegexOptions.ExplicitCapture);
static Regex extractArgsRegex = new Regex(@"([^,]+\(.+?\))|([^,]+)");
static void Main(string[] args)
{
string test = @"add(1, 2, sub(4, add(1, 2)), div(4, 2))";
Console.WriteLine(ParseFunction(test));
Console.ReadLine();
}
static string ParseFunction(string expr)
{
expr = extractFuncRegex.Replace(expr, (m) =>
{
string func = m.Groups["func"].Value;
string param = m.Groups["params"].Value;
Console.WriteLine("Function: {0}", func);
MatchCollection paramCollection = extractArgsRegex.Matches(param);
List<string> pa = new List<string>();
foreach (Match item in paramCollection)
{
string p = item.Groups[0].Value.Trim();
Console.WriteLine("\tParameter: {0}", p);
if (extractFuncRegex.IsMatch(p))
p = ParseFunction(p);
pa.Add(p);
}
switch (func)
{
case "add":
float a1 = 0;
foreach (string item in pa)
a1 += float.Parse(item);
return a1.ToString();
case "sub":
return (float.Parse(pa[0]) - float.Parse(pa[1])).ToString();
case "div":
return (float.Parse(pa[0]) / float.Parse(pa[1])).ToString();
default:
return expr;
}
});
return expr;
}
}
调试的话可以看到,解析有问题
sub(4, add(1, 2))
到目前为止,您显然在这方面做得很好,所以我不会说 "don't use regular expressions, throw it away and use something else" - 我将展示如何通过最少的更改使您的代码正常工作。
首先,将您的 extractFuncRegex
更改为
@"(?<func>add|sub|div)\s*\((?<params>[^()]*)\)"
我已将 params
组中的 .*
替换为 [^()]*
。这意味着它只会匹配 不包含任何其他函数调用 的函数调用 - 因为这是我们唯一可以直接处理的事情。我还删除了尾随 $
以使其正常工作。
现在的诀窍是调用 ParseFunction
或 extractFuncRegex.Replace
直到 没有替换 。例如,您可以像这样将对 extractFuncRegex.Replace
的调用置于循环中(未经测试):
bool doneWork = true;
while (doneWork)
{
doneWork = false;
expr = extractFuncRegex.Replace(expr, (m) =>
{
doneWork = true;
...
});
}
...
使用这个,你会得到一系列逐渐简化的表达式。在每个阶段,只有最深个函数调用被替换。
add(1, 2, sub(4, add(1, 2)), div(4, 2))
|-------- |--------
add(1, 2, sub(4, 3 ), 2 )
|----------------
add(1, 2, 1 , 2 )
|--------------------------------------
6