• 使用正则要注意的几点


    在CSDN上看到一篇关于文章关键字优化的帖子,其中“路过”的回复提到了几点 值得学习

     
    1、不要使用静态方法,而一定要显式的声明Regex对象 
    原因是静态方法会临时创建一个Regex对象,用它来调用请求的方法,然后弃用这个对象。而静态方法每次调用,都必须重新检查正则表达式,所以存在效率缺陷 
    虽然默认情况下,.NET Framework做了缓存处理,但默认只缓存15个正则表达式,尽管可以通过 
    Regex.CacheSize = 123; 
    来调整,但这并不是解决效率问题的根本方法 

    2、不要在循环体中声明Regex对象 
    因为这样使用,每次都要重新创建对象,重新对正则表达式进行编译,大大降低效率 

    3、如果正则需要在循环中调用,且循环次数比较多,正则要先在循环体外预编译,RegexOptions.Compiled  
    预编译会延长编译时间,占用更多的内存,但会加速匹配过程。一般在数据源较大、正则复杂、频繁调用、循环中使用时,可以考虑进行预编译 
    当然,在多处调用,且调用频繁的情况下,可以考虑封装到assembly中 

    4、除非对源字符串的结构非常清楚,否则不要轻易使用.*?这种非贪婪模式,非贪婪模式(exp)*?以及量词的嵌套使用不当,会造成无限循环回溯,通常是正则效率陷阱的根源,尽量使用排除型字符组[^…]和否定的正向环视(?!exp)结合贪婪模式来实现 
    通常情况下, <.+?>是没有 <[^>]*>的效率高的 

    5、匹配失败不需要回溯的子表达式,用固化分组(?>…)加速失败过程,同时避免回溯 
    那么 <[^>]*>通常还可以通过固化分组的方式进行优化 <(?>[^>]*)> 

    所以下面这一部分代码 
    C# code
    for (int i = 0; i < str1.Count; i++) { tmp = new StringBuilder(str1[i]); if (Regex.Replace(tmp.ToString(), @"<.+?>", "").Length > 5) //可以替换为 Regex tagReg = new Regex(@"<(?>[^>]*)>", RegexOptions.Compiled); for (int i = 0; i < str1.Count; i++) { tmp = new StringBuilder(str1[i]); if (tagReg.Replace(tmp.ToString(), "").Length > 5)


    6、以“|”取“或”的分支结构,对效率的影响也很大,所以通常情况下,使用分支结构时,要尽可能的抽象出相同的规律,对分支的复杂度加以简化 
    C# code
    (<a .+?</a>)|(<pre(>|\s).+?</pre>) //可以简化为 <(a|pre)\b(?:(?!</?\1).)*</\1>

    7、在循环中使用,当捕获组没有必须使用的理由时,使用非捕获组代替 
    捕获组匹配成功后,会将匹配的内容保存到一个组里,供以后引用,所以无意义的捕获组,会占用内存,降低效率 

    所以循环体中 
    C# code
    reg2 = new Regex(@"((^|>)[^<]+?)(" + _tag + ")", RegexOptions.IgnoreCase); //以及其后的一行 tmp.Insert(mat2.Index, mat2.Groups[1].Value + "<a href='/tag/" + mat2.Groups[2].Value + ".htm'>" + mat2.Groups[2].Value + "</a>"); //可以替换为 reg2 = new Regex(@"(?<=(?:^|>)(?:(?!" + _tag + ").)*)" + _tag , RegexOptions.IgnoreCase); tmp.Insert(mat2.Index, "<a href='/tag/" + mat2.Value + ".htm'>" + mat2.Value + "</a>");


    受限于楼主的实现思路,reg2这个正则,必须是动态生成的,所以没有办法提取到循环体外,此处对性能的影响较大 

    8、另外,在.NET中动态生成正则表达式时,为了避免存在变量中有正则中具体特殊意义的字符,而导致正则解析失败,抛异常的问题,可以用Regex.Escape()方法对变量进行预处理 
    C# code
    reg2 = new Regex(@"(?<=(?:^|>)(?:(?!" + Regex.Escape(_tag) + ").)*)" + Regex.Escape(_tag) , RegexOptions.IgnoreCase);

  • 相关阅读:
    后缀数组详解
    快速傅里叶变换详解(FFT)
    算法学习————SG函数和SG定理
    noi.ac七一模拟赛
    算法学习————高斯消元
    算法学习————Lucas定理
    算法学习————Kruskal重构树
    算法学习————FWT
    20210629模拟
    复习笔记之背包
  • 原文地址:https://www.cnblogs.com/mad/p/1496661.html
Copyright © 2020-2023  润新知