我们的低级日志记录库必须处理发送给它的各种日志消息。
其中一些消息包括花括号(作为文本的一部分),有些包含使用String.Format
作为字符串一部分格式化的参数例如,此字符串可以是Logger类的输入:
“参数:{Hostname}值:{0}” 使用正确的变量发送以用于格式化程序。
为了正确地做到这一点,我必须逃避不属于格式化的花括号(通过将它们加倍)。
我想过用Regex做这件事,但是这并不像看起来那么简单,因为我不知道如何在花括号内部匹配这些字符串(String.Format未使用的字符串用于格式化)
另一个问题是Logger类应尽可能提高性能,开始处理正则表达式,因为其操作的一部分可能会影响性能。
是否有适当且已知的最佳做法?
答案 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你应该重新设计,以避免日志库需要这样做。