【发布时间】:2021-07-08 21:10:19
【问题描述】:
我正在使用类似的字符串
$upper('anothervalue')$
我写了一个解析器,用下面的代码很好地解析了这个语句。
但是,现在另一个系统正在发送一个复杂的字符串,例如(我可以得到任意数量的链式字符串):
$upper($trim('somevalue')$)$ - $upper('anothervalue')$
如何以特定顺序遍历分层数据以评估函数(从最里面的匹配开始):
$trim('somevalue')$ --我会评估这个,把它存储在变量x中
$upper(x)$ --now 用上一条语句的结果计算上层
$upper('anothervalue')$
private static object EvaluateFunctionsInJson(string jsonValue)
{
object origJsonValue = jsonValue;
var fnMatches = Regex.Matches(jsonValue.ToString(), @"\$(.+?)\$");
var fnCount = fnMatches.Count;
foreach (var fnMatch in fnMatches)
{
// call another method to evaluate the function
object replaceValue = EvaluateFunction(fnMatch.ToString());
if (fnCount > 1)
{
origJsonValue = origJsonValue.ToString().Replace(fnMatch.ToString(), replaceValue.ToString());
}
else
{
origJsonValue = replaceValue;
}
}
return origJsonValue;
}
private static object EvaluateFunction(string jsonValue)
{
var functionWithoutDollarSign = Regex.Replace(jsonValue.ToString(), @"[$$]+", "");
string functionName = Regex.Match(functionWithoutDollarSign, @"\b[A-Za-z]+\b", RegexOptions.Singleline).Value; //get the first word
var functionParam = Regex.Match(functionWithoutDollarSign, @"\(([^)]*)\)").Value; //get the text between paranthesis
var functionParamWithoutParanthesis = Regex.Replace(functionParam.ToString(), @"[\(\)]+", "");
var funcParams = functionParamWithoutParanthesis.Split(',');
var value = funcParams[0];
switch (functionName.ToLower().Trim())
{
case "upper":
return value.ToUpper();
case "lower":
return value.ToLower();
case "number":
return Convert.ToInt64(value);
case "boolean":
return Convert.ToBoolean(value);
default:
return value;
}
}
【问题讨论】:
-
这需要有多复杂?您可能可以迭代地执行此操作,但它会很痛苦并且无法很好地扩展。您可以尝试使用递归做一些事情,但我认为在这种情况下使用表达式树会更好。 docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…
-
我没想到它会如此复杂。只有两个层次——功能下的功能。我以前从未使用过表达式树,需要探索它 - 感谢您的链接。
-
这可能吗? “开始美元”和“结束美元”符号之间没有区别,那么您应该如何区分以表达式开头的美元符号和以表达式结尾的美元符号呢?就像,上面你更复杂的表达是“打开,打开,关闭,关闭,打开,关闭”,但你怎么知道它不是“打开,关闭,打开,关闭,打开,关闭”?
-
进一步思考:如果每个“开盘美元”后面都有一个已知关键字(“upper”、“trim”等),我想你可以先替换所有 那些 带有开始标记和关键字的实例,然后将所有剩余的美元符号替换为结束标记,然后您就会知道打开和关闭...
-
我不明白结束美元符号的必要性。为什么不干脆做类似
$upper($trim('somevalue')) - $upper('anothervalue')之类的事情,其中美元符号表示“函数”的开始,然后美元符号之后是函数名称,函数的参数用括号括起来。