字符串.用大括号格式化

本文关键字:格式化 字符串 | 更新日期: 2023-09-27 18:14:31

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

其中一些消息包含花括号(作为文本的一部分),有些消息包含要使用string格式化为字符串的一部分的参数。格式的

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

"参数:{主机名}值:{0}"使用发送给格式化程序使用的正确变量。

为了正确地完成它,我必须转义不属于格式的花括号(通过将它们加倍)。

我想用Regex来做,然而这并不像看起来那么简单,因为我不知道如何在花括号内匹配这些字符串(那些不被字符串使用的字符串)。用于格式化目的的格式)。

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

是否有适当的和已知的最佳实践?

字符串.用大括号格式化

在一个正则表达式中完成:

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

输出:

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

当然,这只适用于没有任何包含数字的参数,但仍然应该用{{ }}

转义。

我认为您应该查看您的日志记录器接口。比较Console.WriteLine的工作方式:

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

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

我会将所有的花括号翻倍,然后我会寻找那些被替换为像{{'d+}}这样的正则表达式,这样它们就会回到原来的格式——{{0}}=>{0}——在你的字符串中。
因此,对于每一行,我将像这样做

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

所以这是对最初问题的技术性回答,但是@Anders Abel是完全正确的。这个设计值得再考虑一下。

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

Logger.Log("{0:dd/mm/yyy} {0:hh:mm:ss} {hostname} {123Component}上发生{1:x4}错误",日期时间。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的观点,您应该重新设计以避免需要日志库来做这些