如何替换字符串模板上的标记? [英] How to replace tokens on a string template?
问题描述
我正在尝试学习编写一个基本的模板引擎实现.例如我有一个字符串:
I'm attempting to learn to write a basic template engine implementation. For example I have a string:
string originalString = "The current Date is: {{Date}}, the time is: {{Time}}";
读取每个 {{}}
的内容然后用有效字符串替换整个标记的最佳方法是什么?
what is the best way of reading the contents of each {{}}
and then replacing the whole token with the valid string?
感谢 BrunoLM 为我指明了正确的方向,到目前为止,这就是我所拥有的,它解析得很好,还有什么我可以做的事情来优化这个功能吗?
Thanks to BrunoLM for pointing me in the right direction, so far this is what I have and it parses just fine, is there any other things I can do to optimize this function?
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;
}
});
}
推荐答案
简短回答
我认为最好使用正则表达式.
Short answer
I think it would be best to use a Regex.
var result = Regex.Replace(str, @"{{(?<Name>[^}]+)}}", m =>
{
return m.Groups["Name"].Value; // Date, Time
});
<小时>
在 c#-6.0 你可以使用:
string result = $"Time: {DateTime.Now}";
<小时>
String.Format &IFormattable
但是,已经有一种方法可以做到这一点.文档.
String.Format("The current Date is: {0}, the time is: {1}", date, time);
此外,您可以使用带有 IFormattable
的类.我没有进行性能测试,但这个测试可能很快:
And also, you can use a class with IFormattable
. I didn't do performance tests but this one might be fast:
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);
<小时>
检查您的代码和详细信息
在您当前使用的代码中
Review of your code and detailed information
In your current code you are using
// match.Value = {{Date}}
match.Value.Substring(2, match.Value.Length - 4).Replace(" ", String.Empty);
相反,如果你看我上面的代码,我使用了模式
Instead, if you look at my code above, I used the pattern
@"{{(?<Name>[^}]+)}}"
语法 (?
表示这是一个 命名组,你可以在这里查看文档.
The syntax (?<SomeName>.*)
means this is a named group, you can check the documentation here.
它允许您访问 match.Groups["SomeName"].Value
这将等同于该组的模式.所以它会匹配两次,返回日期"然后是时间",所以你不需要使用SubString
.
It allows you to access match.Groups["SomeName"].Value
which will be equivalent to the pattern with this group. So it would match two times, returning "Date" and then "Time", so you don't need to use 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 字段:
To improve even more, you can have a static compiled Regex field:
private static Regex RegexTemplate = new Regex(@"{{(?<Param>.*?)}}", RegexOptions.Compiled);
然后用作
RegexTemplate.Replace(str, match => ...);
这篇关于如何替换字符串模板上的标记?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!