用值替换变量名

本文关键字:变量名 替换 | 更新日期: 2023-09-27 18:28:13

我定义了一个具有以下值的字符串:

var filterMe = "foo=1;bar=foo+5;foobar=foo+5-bar;";

并创建一个数组来分割字符串,如下所示:

var splitter = filterMe.Split(';');
Dictionary<string,string> dictionary = new Dictionary<string, string>();
foreach (var split in splitter)
        {
            if (!string.IsNullOrEmpty(split))
            {
                var part = split.Split('=');
                dictionary.Add(part[0], part[1]);
            }
        }

因此,字典中"bar=foo+5"的结果定义为"bar","foo+5"。

现在我的问题是,如何将值"foo+5"中的"foo"更改为包含值"1"的键"foo)字符串filterMe将更长且动态,因此它将包含多个变量(foo)。

编辑:由于我的问题似乎有点令人困惑,请参阅下面的更换方法:

var foo=200;
var bar = foo+300;

可变条应变为:

var bar = 200+300;

用值替换变量名

这个库似乎可以满足您的需要http://csharpeval.codeplex.com/wikipage?title=Usage&referringTitle=主页

完成拆分后,按顺序遍历字典中的每个值,并将这些值(foo)作为临时动态对象的成员(如果您使用的是.net4,如果不是字典)。

然后使用库计算第二个表达式,将结果存储在临时对象/字典中,然后继续。

您还需要一个变量及其值的数组或字典(例如Foo,5)。将分号(filterMe.Split(";")上的字符串拆分为一个数组以获取元素,然后循环并拆分"="上的元素,使用返回数组的array[0]作为字典中的键,array[1]作为值。最后循环遍历变量和值的数组,用它们的正确值替换键。为了执行计算(例如foo-5),我会创建一个Func<string, string, int>,它从字典中接受要执行计算的2个int作为字符串,删除运算符,将它们解析为int,然后使用运算符的字符串来决定执行哪个运算(+、-等),最后返回计算值的int(或我猜是字符串)

以下测试通过:(完全没有考虑性能

[Test]
public void tst()
{
    var filterMe = "foo=1;bar=foo+5;foobar=foo+5-bar;";
    var dic = filterMe.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
                      .ToDictionary(x => x.Split('=')[0], x => x.Split('=')[1]);
    while (true)
    {
        var kvpToApply = dic.Keys
                            .Join(dic, x => true, y => true, (key, value) => new { key, value })
                            .FirstOrDefault(x => x.value.Value.Contains(x.key));
        if (kvpToApply != null)
        {
            dic[kvpToApply.value.Key] = kvpToApply.value.Value.Replace(kvpToApply.key, dic[kvpToApply.key]);
        }
        else
        {
            break;
        }
    }
    Assert.AreEqual("1", dic["foo"]);
    Assert.AreEqual("1+5", dic["bar"]);
    Assert.AreEqual("1+5-1+5", dic["foobar"]);
}

这将起作用:

public enum ParserState
{
    ExpectSign = 0,
    ExpectValue = 1
}
public static void Parse()
{
    string filterMe = "foo=1;bar=foo+5;foobar=foo+5-bar;";
    var rows = filterMe.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
    Dictionary<string, int> locals = new Dictionary<string, int>();
    foreach (string split in rows)
    {
        var row = split.Split('=');
        if (row.Length != 2)
        {
            throw new Exception();
        }
        string name = row[0].Trim();
        string exp = row[1].Trim();
        if (!Regex.IsMatch(name, "^[A-Za-z_]+$"))
        {
            throw new Exception();
        }
        Regex rx = new Regex(@"'G(?:(?<local>[A-Za-z_]+)|(?<constant>[0-9]+)|(?<sign>[+-]))");
        var subExps = rx.Matches(exp).OfType<Match>().ToArray();
        if (subExps.Length == 0 || subExps[subExps.Length - 1].Index + subExps[subExps.Length - 1].Length != exp.Length)
        {
            throw new Exception();
        }
        int result = 0;
        ParserState state = ParserState.ExpectValue;
        string currentSign = "+";
        foreach (var subExp in subExps)
        {
            {
                Group sign = subExp.Groups["sign"];
                if (sign.Success)
                {
                    if (state != ParserState.ExpectSign)
                    {
                        throw new Exception();
                    }
                    currentSign = sign.ToString();
                    state = ParserState.ExpectValue;
                    continue;
                }
            }
            {
                Group local = subExp.Groups["local"];
                if (local.Success)
                {
                    if (state != ParserState.ExpectValue)
                    {
                        throw new Exception();
                    }
                    int value;
                    if (!locals.TryGetValue(local.ToString(), out value))
                    {
                        throw new Exception();
                    }
                    result = Operation(result, value, currentSign);
                    state = ParserState.ExpectSign;
                }
            }
            {
                Group constant = subExp.Groups["constant"];
                if (constant.Success)
                {
                    if (state != ParserState.ExpectValue)
                    {
                        throw new Exception();
                    }
                    int value = int.Parse(constant.ToString());
                    result = Operation(result, value, currentSign);
                    state = ParserState.ExpectSign;
                }
            }
            if (state != ParserState.ExpectSign)
            {
                throw new Exception();
            }
        }
        locals[name] = result;
    }
}
private static int Operation(int result, int value, string currentSign)
{
    if (currentSign == "+")
    {
        return result + value;
    }
    if (currentSign == "-")
    {
        return result - value;
    }
    throw new ArgumentException();
}

但请注意,如果您想在运算符之间引入()或不同的优先级(因此1 * 2 + 3 == (1 * 2) + 3)或数字符号(因此1 + -2)或(-2 + 1),这将变得非常困难。

有一些仪器/库可以做这类事情。

最后,它考虑了以这种格式制作的"行":

local = [local|constant]([+|-][local|constant])*