Строка.Формат с фигурными скобками
наша низкоуровневая библиотека журналов должна справляться со всеми видами сообщений журнала, отправленных в нее.
некоторые из этих сообщений включают фигурные скобки (как часть текста), а некоторые содержат параметры, которые будут отформатированы как часть строки с помощью String.Формат
например, эта строка может быть входом в класс Logger:
"Параметр: {Имя Хоста} Значение: {0}" С правильной переменной, отправленной для использования в formatter.
для того, чтобы правильно сделать это, я должен избежать фигурных скобок, которые не являются частью форматирования (путем их удвоения).
Я думал сделать это с помощью Regex, однако это не так просто, как может показаться, так как я понятия не имею, как сопоставить эти строки внутри фигурных скобок (те, которые не используются String.Формат для форматирования).
другая проблема заключается в том, что класс Logger должен быть максимально эффективным, начиная обрабатывать регулярные выражения как часть своей работы может препятствовать производительности.
есть ли какая-либо правильная и известная лучшая практика для этого?
4 ответов
делать это всего за одно регулярное выражение:
string input = "Parameter: {Hostname} Value: {0}";
input = Regex.Replace(input, @"{([^[0-9]+)}", @"{{}}");
Console.WriteLine(input);
выходы:
Параметр: {{Hostname}} Значение: {0}
Это, конечно, работает только до тех пор, пока нет никаких параметров, которые содержат числа, но все равно должны быть экранированы с {{ }}
Я думаю, что вы должны заглянуть в интерфейс loggers. Сравнить с тем, как Console.WriteLine
работает:
-
Console.WriteLine(String)
выводит именно строку, без форматирования, ничего особенного С { и }. -
Console.WriteLine(String, Object[])
выходы с использованием форматирования. { и } - это специальные символы, которые вызывающий должен избежать в {{ и }}
Я думаю, что это дефектный дизайн, который должен различать различные фигурные скобки в коде, чтобы узнать, что это значит. Положите бремя побега { , которое должно произойти на выходе в {{.
Я бы удвоил все фигурные скобки, а затем я бы искал те, которые будут заменены регулярным выражением, как {{\d+}}
чтобы они вернулись к исходному формату -- {{0}} => {0} -- в твоей веревочке.
Поэтому для каждой строки Я бы сделал sth так
string s = input.Replace("{", "{{").Replace("}", "}}");
return Regex.Replace(s, @"{{(?<val>\d+)}}",
m => { return "{" + m.Groups["val"] + "}"; }));
Так что это технический ответ на исходный вопрос, но @Anders Abel совершенно прав. Стоит еще раз рассмотреть проект...
чтобы абонент мог иметь отформатированные строки и справиться с formitting спецификаторы например
регистратор.Log ("{0:dd/mm/yyy} {0:hh:mm:ss} {имя хоста} произошла ошибка {1: x4} на {123Component}!", значение 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, "{}");
Console.WriteLine(output);
вот результаты:
"{0:dd/mm/yyy} {0:hh:mm:ss} {{hostname}} Some error {1:x4} happened on {{123Component}}!"
но повторяю, я согласен с Андерсом Абелем, что вы должны перепроектировать, чтобы избежать необходимости в библиотеке журналов для этого.