Лучший способ заменить токены в большом текстовом шаблоне

У меня есть большой текстовый шаблон, который требует, чтобы разделы были заменены другим текстом. Токены выглядят примерно так: ## USERNAME ##. Мой первый инстинкт - это просто использовать String.Replace(), но есть ли более эффективный или более эффективный способ Replace()?

Ответы

Ответ 1

System.Text.RegularExpressions.Regex.Replace() - это то, что вы ищете - ЕСЛИ ваши жетоны достаточно странны, вам нужно найти регулярное выражение.

Некоторая душа сделала некоторые тесты производительности, а также между Regex.Replace(), String.Replace() и StringBuilder.Replace(), String.Replace() действительно вышел сверху.

Ответ 2

Единственная ситуация, в которой я должен был это сделать, - отправить шаблонное электронное письмо. В .NET это предоставляется из коробки класс MailDefinition. Таким образом, вы создаете шаблонное сообщение:

MailDefinition md = new MailDefinition();
md.BodyFileName = pathToTemplate;
md.From = "[email protected]";

ListDictionary replacements = new ListDictionary();
replacements.Add("<%To%>", someValue);
// continue adding replacements

MailMessage msg = md.CreateMailMessage("[email protected]", replacements, this);

После этого msg.Body будет создан путем замены значений в шаблоне. Я думаю, вы можете взглянуть на MailDefinition.CreateMailMessage() с Reflector:). Извините за то, что вы немного не по теме, но если это ваш сценарий, я думаю, что это самый простой способ.

Ответ 3

Ну, в зависимости от того, сколько переменных у вас есть в вашем шаблоне, сколько у вас шаблонов и т.д. это может быть работа для полного процессора шаблонов. Единственный, который я когда-либо использовал для .NET, - NVelocity, но я уверен, что там должно быть множество других, большинство из них связаны с некоторыми веб-фреймами или другими.

Ответ 4

string.Replace отлично. Я бы предпочел использовать Regex, но я *** для регулярных выражений.

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

Но для наивной реализации string.Replace должен быть в порядке.

Ответ 5

Если вы выполняете несколько заметок на больших строках, лучше использовать StringBuilder.Replace(), так как появятся обычные проблемы с производительностью со строками.

Ответ 6

Пришлось сделать что-то подобное недавно. Я сделал это:

  • сделать метод, который принимает словарь (key = имя токена, value = текст, который нужно вставить)
  • Получите все совпадения в вашем формате токена (##. +? ## в вашем случае, я думаю, не так хорошо в регулярных выражениях: P) с использованием Regex.Matches(ввод, регулярное выражение)
  • foreach по результатам, используя словарь, чтобы найти значение вставки для вашего токена.
  • возвращает результат.

Готово; -)

Если вы хотите проверить свои регулярные выражения, я могу предложить регулятор.

Ответ 7

Регулярные выражения будут самым быстрым решением для кода, но если у вас много разных токенов, он будет медленнее. Если производительность не является проблемой, используйте эту опцию.

Лучшим подходом было бы определить токен, например, ваш "##", который вы можете сканировать в тексте. Затем выберите, что заменить из хэш-таблицы текстом, который следует за токеном в качестве ключа.

Если это часть сборки script, то у nAnt есть отличная возможность для этого сделать Filter Chains. Код для этого является открытым исходным кодом, поэтому вы можете посмотреть, как это делается для быстрой реализации.

Ответ 8

FastReplacer реализует замену токена в O (n * log (n) + m) и использует 3x память исходной строки.

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

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

Мы разработали FastReplacer, чтобы помочь нам в проекте, где нам нужно было создать большой текст с большим количеством операций добавления и замены. Первая версия приложения заняла 20 секунд, чтобы сгенерировать текст с помощью StringBuilder. Вторая улучшенная версия, которая использовала класс String, заняла 10 секунд. Затем мы внедрили FastReplacer, а продолжительность - 0,1 секунды.

Ответ 10

Если ваш шаблон большой, и у вас много токенов, вы, вероятно, не хотите его перемещать и заменять токен в шаблоне один за другим, так как это приведет к операции O (N * M), где N - размер шаблона, а M - количество заменяемых токенов.

Следующий метод принимает шаблон и словарь пар значений ключей, которые вы хотите заменить. Путем инициализации StringBuilder немного больше, чем размер шаблона, это должно привести к операции O (N) (то есть, ей не нужно увеличивать сам журнал N раз).

Наконец, вы можете переместить здание токенов в Singleton, поскольку его нужно только создать.

static string SimpleTemplate(string template, Dictionary<string, string> replacements)
{
   // parse the message into an array of tokens
   Regex regex = new Regex("(##[^#]+##)");
   string[] tokens = regex.Split(template);

   // the new message from the tokens
   var sb = new StringBuilder((int)((double)template.Length * 1.1));
   foreach (string token in tokens)
      sb.Append(replacements.ContainsKey(token) ? replacements[token] : token);

   return sb.ToString();
}