【问题标题】:How to replace tokens on a string template? [closed]如何替换字符串模板上的标记? [关闭]
【发布时间】:2013-12-18 07:11:04
【问题描述】:

我正在尝试学习编写一个基本的模板引擎实现。例如我有一个字符串:

string originalString = "The current Date is: {{Date}}, the time is: {{Time}}";

读取每个{{}} 的内容然后用有效字符串替换整个令牌的最佳方法是什么?

编辑:感谢 BrunoLM 为我指明了正确的方向,到目前为止,这就是我所拥有的,它解析得很好,我还能做些什么来优化这个功能吗?

private const string RegexIncludeBrackets = @"{{(.*?)}}";

public static string ParseString(string input)
{
    return Regex.Replace(input, RegexIncludeBrackets, match =>
    {
        string cleanedString = match.Value.Substring(2, match.Value.Length - 4).Replace(" ", String.Empty);
        switch (cleanedString)
        {
            case "Date":
                return DateTime.Now.ToString("yyyy/MM/d");
            case "Time":
                return DateTime.Now.ToString("HH:mm");
            case "DateTime":
                return DateTime.Now.ToString(CultureInfo.InvariantCulture);
            default:
                return match.Value;
        }
    });
}

【问题讨论】:

  • 努力努力!!!。一个简单的谷歌搜索就可以了
  • 这里是提示,从 msdn 阅读 boxing/unboxingString.Format
  • template engine implementation 的可能重复项
  • @BrunoLM 如果 OP 表现出最轻微的努力解决他的问题的迹象,我会很乐意提供帮助。我想知道为什么这是来自 20k+ 代表用户

标签: c# template-engine


【解决方案1】:

简答

我认为最好使用正则表达式。

var result = Regex.Replace(str, @"{{(?<Name>[^}]+)}}", m =>
{
    return m.Groups["Name"].Value; // Date, Time
});

你可以使用:

string result = $"Time: {DateTime.Now}";

String.Format & IFormattable

但是,已经有一种方法可以做到这一点。 Documentation.

String.Format("The current Date is: {0}, the time is: {1}", date, time);

此外,您还可以使用带有IFormattable 的类。我没有做性能测试,但这个可能很快:

public class YourClass : IFormattable
{
    public string ToString(string format, IFormatProvider formatProvider)
    {
        if (format == "Date")
            return DateTime.Now.ToString("yyyy/MM/d");
        if (format == "Time")
            return DateTime.Now.ToString("HH:mm");
        if (format == "DateTime")
            return DateTime.Now.ToString(CultureInfo.InvariantCulture);

        return format;

        // or throw new NotSupportedException();
    }
}

并用作

String.Format("The current Date is: {0:Date}, the time is: {0:Time}", yourClass);

审查您的代码和详细信息

在您当前使用的代码中

// match.Value = {{Date}}
match.Value.Substring(2, match.Value.Length - 4).Replace(" ", String.Empty);

相反,如果您查看我上面的代码,我使用了模式

@"{{(?<Name>[^}]+)}}"

语法(?&lt;SomeName&gt;.*) 表示这是named group, you can check the documentation here.

它允许您访问match.Groups["SomeName"].Value,这将等效于该组的模式。所以它会匹配两次,返回“日期”然后返回“时间”,所以你不需要使用SubString

更新你的代码,它会是

private const string RegexIncludeBrackets = @"{{(?<Param>.*?)}}";

public static string ParseString(string input)
{
    return Regex.Replace(input, RegexIncludeBrackets, match =>
    {
        string cleanedString = match.Groups["Param"].Value.Replace(" ", String.Empty);
        switch (cleanedString)
        {
            case "Date":
                return DateTime.Now.ToString("yyyy/MM/d");
            case "Time":
                return DateTime.Now.ToString("HH:mm");
            case "DateTime":
                return DateTime.Now.ToString(CultureInfo.InvariantCulture);
            default:
                return match.Value;
        }
    });
}

要进一步改进,您可以使用静态编译的 Regex 字段:

private static Regex RegexTemplate = new Regex(@"{{(?<Param>.*?)}}", RegexOptions.Compiled);

然后用 as

RegexTemplate.Replace(str, match => ...);

【讨论】:

  • 感谢您为我指明正确的方向。我接受了你对正则表达式的初步想法并添加了它
  • 没问题,很高兴我能帮上忙。
猜你喜欢
  • 1970-01-01
  • 2014-07-21
  • 1970-01-01
  • 2020-06-07
  • 2016-11-07
  • 1970-01-01
  • 2011-07-16
  • 1970-01-01
相关资源
最近更新 更多