代码之家  ›  专栏  ›  技术社区  ›  jeremcc chris

替换大型文本模板中标记的最佳方法

  •  13
  • jeremcc chris  · 技术社区  · 17 年前

    我有一个大的文本模板,需要用其他文本替换标记化的部分。令牌看起来像这样:用户名。我的第一直觉是只使用string.replace(),但是有没有更好、更有效的方法,或者replace()已经对此进行了优化?

    10 回复  |  直到 13 年前
        1
  •  12
  •   Greg Hurlman    17 年前

    System.Text.RegularExpressions.Regex.Replace() 如果你的令牌足够奇怪,你需要一个regex来找到它们,那么这就是你要寻找的。

    Some kind soul did some performance testing ,在regex.replace()、string.replace()和stringbuilder.replace()之间,string.replace()实际上位于顶部。

        2
  •  7
  •   Slavo    17 年前

    我唯一需要做的就是发送一封模板电子邮件。在.NET中,这是由 MailDefinition class . 这就是创建模板化消息的方法:

    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。我想你可以看看maildefinition.createMailMessage()和reflector:。很抱歉有点偏离主题,但如果这是你的场景,我认为这是最简单的方法。

        3
  •  3
  •   dguaraglia    17 年前

    嗯,这取决于模板中有多少个变量,有多少个模板,等等。对于完整的模板处理器来说,这可能是一个工作。我在.NET上唯一用过的是 NVelocity 但是我相信一定有很多其他的网站,其中大多数都链接到了一些网络框架或者其他的。

        4
  •  2
  •   Will    17 年前

    字符串。替换可以。我更喜欢使用regex,但我是***用于正则表达式。

    要记住的是这些模板有多大。如果它真的很大,内存也是一个问题,那么您可能需要创建一个自定义的标记器,它在流上工作。这样,您在操作文件时,只能将文件的一小部分保存在内存中。

    但是,对于naive实现,string.replace应该可以。

        5
  •  2
  •   samjudson    17 年前

    如果在大字符串上执行多个替换,那么最好使用StringBuilder.Replace(),因为字符串通常会出现性能问题。

        6
  •  2
  •   Gareth Farrington    17 年前

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

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

    如果这是构建脚本的一部分,那么nant有一个很好的特性来完成这个任务 Filter Chains . 它的代码是开放源码的,因此您可以查看它是如何快速实现的。

        7
  •  2
  •   Erik van Brakel scottrakes    17 年前

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

    • 生成一个采用字典的方法(key=token name,value=the text you need to insert)
    • 获取与令牌格式(.+)匹配的所有内容。##在您的例子中,我猜,不太擅长正则表达式:p)使用regex.matches(输入,正则表达式)
    • foreach遍历结果,使用字典查找令牌的插入值。
    • 返回结果。

    完成;-)

    如果你想测试你的正则表达式,我可以建议 the regulator.

        8
  •  2
  •   Eric J.    13 年前

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

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

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

    我们设计了FastReplacer来帮助我们完成一个项目,在这个项目中,我们必须用大量的附加和替换操作生成一个大文本。应用程序的第一个版本使用StringBuilder生成文本耗时20秒。使用字符串类的第二个改进版本用了10秒。然后我们实现了fastreplacer,持续时间下降到0.1秒。

        9
  •  1
  •   Factor Mystic    17 年前

    这是正则表达式的理想用法。退房 this helpful website , the .Net Regular Expressions class 以及这本非常有帮助的书 Mastering Regular Expressions .

        10
  •  1
  •   ThisGuy    14 年前

    如果您的模板很大,并且您有很多令牌,那么您可能不想一个一个地遍历它并替换模板中的令牌,因为这将导致一个O(n*m)操作,其中n是模板的大小,m是要替换的令牌数。

    下面的方法接受要替换的键值对的模板和字典。通过将StringBuilder初始化为略大于模板的大小,它将导致O(N)操作(即,它不必增长自己的日志n次)。

    最后,您可以将令牌的构建移动到一个单例中,因为它只需要生成一次。

    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();
    }
    
    推荐文章