在C#中解析含嵌套括号的VFP复杂ABS计算字符串
解决方案
一、提取嵌套ABS()调用的实现
正则没法处理嵌套括号,用栈来处理最靠谱,逻辑很直接:
- 遍历字符串,碰到
ABS(就记下起始位置,同时初始化括号计数器 - 遇到左括号计数器+1,右括号计数器-1
- 计数器回到0时,从起始位置到当前右括号的子串就是完整的ABS调用
代码实现:
public static List<string> ExtractAbsCalls(string expression) { var absCalls = new List<string>(); int startPos = -1; int bracketCount = 0; for (int i = 0; i < expression.Length; i++) { // 匹配ABS(的起始位置 if (i + 3 < expression.Length && expression.Substring(i, 4) == "ABS(") { startPos = i; bracketCount = 1; i += 3; // 跳过已匹配的ABS(字符 continue; } if (startPos != -1) { if (expression[i] == '(') bracketCount++; else if (expression[i] == ')') { bracketCount--; // 括号完全闭合,截取完整ABS调用 if (bracketCount == 0) { absCalls.Add(expression.Substring(startPos, i - startPos + 1)); startPos = -1; } } } } return absCalls; }
调用这个方法传入目标表达式,就能得到需要的ABS列表,之后把每个ABS(替换成Math.Abs(即可。
二、直接评估表达式的工具
DataTable.Compute不兼容VFP的ABS语法,推荐两个实用库:
1. NCalc
支持自定义函数映射,直接把VFP的ABS转成C#的Math.Abs,然后计算:
using NCalc; public static bool EvaluateVfpExpression(string expression) { var expr = new Expression(expression); // 注册ABS函数映射 expr.EvaluateFunction += (funcName, args) => { if (funcName.Equals("ABS", StringComparison.OrdinalIgnoreCase)) { var val = Convert.ToDouble(args.Parameters[0].Evaluate()); args.Result = Math.Abs(val); } }; return Convert.ToBoolean(expr.Evaluate()); }
需要通过NuGet安装NCalc包。
2. Roslyn脚本引擎
先把表达式里的ABS替换成Math.Abs,再用Roslyn动态编译执行:
using Microsoft.CodeAnalysis.CSharp.Scripting; using Microsoft.CodeAnalysis.Scripting; public static async Task<bool> EvaluateWithRoslyn(string expression) { // 替换所有ABS为Math.Abs var csharpExpr = expression.Replace("ABS(", "Math.Abs("); // 配置脚本环境,引入System和Math所在的程序集 var scriptOptions = ScriptOptions.Default .WithReferences(typeof(Math).Assembly) .WithImports("System"); return await CSharpScript.EvaluateAsync<bool>(csharpExpr, scriptOptions); }
需要安装NuGet包Microsoft.CodeAnalysis.CSharp.Scripting。
内容的提问来源于stack exchange,提问作者MattCash
相关产品推荐
相关产品推荐

