带花括号的String.Format

时间:2011-11-15 08:04:11

标签: c# string string-formatting curly-braces

我们的低级日志记录库必须处理发送给它的各种日志消息。

其中一些消息包括花括号(作为文本的一部分),有些包含使用String.Format

作为字符串一部分格式化的参数

例如,此字符串可以是Logger类的输入:

“参数:{Hostname}值:{0}” 使用正确的变量发送以用于格式化程序。

为了正确地做到这一点,我必须逃避不属于格式化的花括号(通过将它们加倍)。

我想过用Regex做这件事,但是这并不像看起来那么简单,因为我不知道如何在花括号内部匹配这些字符串(String.Format未使用的字符串用于格式化)

另一个问题是Logger类应尽可能提高性能,开始处理正则表达式,因为其操作的一部分可能会影响性能。

是否有适当且已知的最佳做法?

4 个答案:

答案 0 :(得分:3)

只用一个正则表达式:

string input = "Parameter: {Hostname} Value: {0}";
input = Regex.Replace(input, @"{([^[0-9]+)}", @"{{$1}}");
Console.WriteLine(input);

输出:

  

参数:{{Hostname}}值:{0}

这当然只有在没有任何参数包含数字但仍应使用{{ }}进行转义的情况下才有效

答案 1 :(得分:2)

我会将所有花括号加倍,然后我会寻找那些用{{\d+}}这样的正则表达式替换它们,以便它们恢复原来的格式 - {{0}} => {0} - 在你的字符串中。
所以对于每一行,我都会这样做

string s = input.Replace("{", "{{").Replace("}", "}}");
return Regex.Replace(s, @"{{(?<val>\d+)}}", 
                     m => { return "{" + m.Groups["val"] + "}"; }));

这是原始问题的技术答案,但@Anders Abel是完全正确的。再次考虑设计是值得的......

答案 2 :(得分:2)

我认为您应该查看您的记录器界面。与Console.WriteLine的工作方式进行比较:

  • Console.WriteLine(String)完全输出给定的字符串,没有格式化,与{和}无关。
  • Console.WriteLine(String, Object[])使用格式输出。 {和}是调用者必须转义为{{和}}
  • 的特殊字符

我认为有缺陷的设计必须区分代码中不同的花括号出现,以找出其含义。将输出中应该出现的转义负担{{。

答案 3 :(得分:2)

允许调用者具有格式化字符串并处理许可说明符,例如

Logger.Log(“{0:dd / mm / yyy} {0:hh:mm:ss} {hostname} {123Component}上发生了一些错误{1:x4}!”,DateTime.UtcNow,257)

你需要一个正则表达式:

string input = "{0:dd/mm/yyy} {0:hh:mm:ss} {hostname} Some error {1:x4} happened on {123Component}!";
Regex reg = new Regex(@"(\{[^[0-9}]+?[^}]*\}|\{(?![0-9]+:)[^}]+?\})");
string output = reg.Replace(input, "{$1}");
Console.WriteLine(output);

输出:

"{0:dd/mm/yyy} {0:hh:mm:ss} {{hostname}} Some error {1:x4} happened on {{123Component}}!"

但重申一点,我同意Anders Abel你应该重新设计,以避免日志库需要这样做。