Строка.Формат с фигурными скобками

наша низкоуровневая библиотека журналов должна справляться со всеми видами сообщений журнала, отправленных в нее.

некоторые из этих сообщений включают фигурные скобки (как часть текста), а некоторые содержат параметры, которые будут отформатированы как часть строки с помощью 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}}!"

но повторяю, я согласен с Андерсом Абелем, что вы должны перепроектировать, чтобы избежать необходимости в библиотеке журналов для этого.