繁体   English   中英

在大文本模板中替换令牌的最佳方法

[英]Best way to replace tokens in a large text template

我有一个很大的文本模板,需要将标记化的部分替换为其他文本。 令牌看起来像这样:## USERNAME ##。 我的第一个本能只是使用String.Replace(),但是有没有更好,更有效的方法,或者Replace()已经为此进行了优化?

System.Text.RegularExpressions.Regex.Replace()是您要寻找的-如果您的令牌很奇怪,以至于您需要使用正则表达式来查找它们。

某种善良的人进行了一些性能测试 ,并且在Regex.Replace(),String.Replace()和StringBuilder.Replace()和String.Replace()之间居于首位。

我必须要做的唯一情况是发送模板电子邮件。 在.NET中, MailDefinition类提供了开箱即用的功能 因此,这是创建模板消息的方式:

MailDefinition md = new MailDefinition();
md.BodyFileName = pathToTemplate;
md.From = "test@somedomain.com";

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

MailMessage msg = md.CreateMailMessage("test@someotherdomain.com", replacements, this);

此后,将通过替换模板中的值来创建msg.Body。 我想你可以看看带有Reflector的MailDefinition.CreateMailMessage()。 抱歉,我的话题有点偏离,但是如果您的情况如此,我认为这是最简单的方法。

好吧,这取决于模板中有多少变量,模板有多少等,这可能是完整模板处理器的工作。 我曾经用于.NET的唯一工具是NVelocity ,但是我敢肯定那里肯定有很多其他工具,其中大多数都链接到某个Web框架或另一个Web框架。

FastReplacer在O(n * log(n)+ m)的时间内实现令牌替换,并使用原始字符串内存的3倍。

当性能很重要时,FastReplacer非常适合在大型字符串上执行许多替换操作。

主要思想是避免每次替换字符串时修改现有文本或分配新的内存。

我们设计了FastReplacer来帮助我们处理一个项目,在该项目中我们不得不生成带有大量追加和替换操作的大文本。 该应用程序的第一个版本使用StringBuilder花费了20秒来生成文本。 使用String类的第二个改进版本花费了10秒。 然后,我们实现了FastReplacer,并将持续时间降至0.1秒。

string.Replace很好。 我更喜欢使用正则表达式,但是对于正则表达式我是***。

要记住的是这些模板的大小。 如果确实很大,并且内存是个问题,则可能要创建一个对流进行操作的自定义标记生成器。 这样,您在操作文件时只将其一小部分保存在内存中。

但是,对于幼稚的实现,string.Replace应该很好。

如果要对大字符串进行多次替换,则最好使用StringBuilder.Replace(),因为通常会出现字符串性能问题。

最近不得不做类似的事情。 我所做的是:

  • 制作一个需要字典的方法(键=令牌名称,值=您需要插入的文本)
  • 使用Regex.Matches(输入,正则表达式)获取与您的令牌格式(我猜是##。+?##的所有匹配项,对正则表达式:P不太好)
  • 使用字典查找结果,以查找令牌的插入值。
  • 返回结果。

完成;-)

如果您想测试您的正则表达式,我可以建议调节器。

正则表达式将是最快的编码解决方案,但是如果您有许多不同的标记,那么它将变得更慢。 如果性能不是问题,请使用此选项。

更好的方法是定义令牌,例如可以在文本中扫描的“ ##”。 然后从哈希表中选择要替换的内容,并以令牌后的文本作为键。

如果这是构建脚本的一部分,则nAnt具有一个很棒的功能,称为“ 过滤链” 该代码是开源的,因此您可以查看如何实现快速实现。

如果您的模板很大并且有很多令牌,那么您可能不想遍历它,并一一替换令牌,因为那样会导致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();
}

这是正则表达式的理想用法。 请访问此有用的网站.Net正则表达式类以及这本非常有用的书“ 掌握正则表达式”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM