C# 通过在大文本上多次调用Regex.IsMatch优化性能

C# 通过在大文本上多次调用Regex.IsMatch优化性能,c#,regex,C#,Regex,我有一个长文本(50-60KB),需要对它运行几个正则表达式(总共大约100条规则)。然而,这是如此缓慢,它基本上不工作 我所做的就是围绕规则创建一个循环,其中每个规则执行一个Regex.IsMatch() 有没有办法优化这一点 更新 每个规则正在执行的操作的示例代码: public class SomeRegexInterceptor : ValidatorBase { private readonly Regex _rgx = new Regex("some rege

我有一个长文本(50-60KB),需要对它运行几个正则表达式(总共大约100条规则)。然而,这是如此缓慢,它基本上不工作

我所做的就是围绕规则创建一个循环,其中每个规则执行一个
Regex.IsMatch()

有没有办法优化这一点

更新

每个规则正在执行的操作的示例代码:

public class SomeRegexInterceptor : ValidatorBase
    {
        private readonly Regex _rgx = new Regex("some regex", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline); 

        public override void Intercept(string html, ValidationResultCollection collection)
        {
            if (!_rgx.IsMatch(html)) return;

            /* do something irrelevant here */
        }
    }

使用Regex替换最重要的一点是如何以及在何处声明Regex不要在循环中初始化正则表达式对象。

创建一个静态类并添加
publicstaticreadonly
Regex字段和
RegexOptions.Compiled
标志集

然后,在任何需要的地方使用它们,使用类似于
myregexportss.LeadingWhitespace.Replace(str,string.Empty)
的东西

请注意,如果您需要使用
Regex.Replace
,则无需检查之前是否与
Regex.IsMatch
匹配

阅读并遵循中概述的建议,即:


也可以考虑逐行处理文件,避免没有它们的正则表达式。

< P>可以将规则合并成一条规则吗?例如:如果您正在为“aaa”执行一个正则表达式,然后为“bbb”执行一个正则表达式,则组合到“aaa | bbb”中可以大大提高性能(而不是运行两个单独的正则表达式)。我以前曾以这种方式以编程方式组合过大量正则表达式,这会产生巨大的性能差异。

组合表达式 如果您能够在运行规则之前执行工作,那么可以将正则表达式与
|
组合在一起,一次完成搜索。然后在你的规则中,你不会像以前那样匿名检查匹配,而是按组名检查匹配。比如说

>((?<Ex1>expression1)|(?<Ex2>expression2)|(?<Ex3>expression3))
((?表达式1)|(?表达式2)|(?表达式3))
因此,关心组
Ex1
的规则检查该组。关心
Ex2
的规则检查
Ex2
等等

此外,您还可以分析正则表达式集并以某种方式优化它们。这将是一个非常有程序性的壮举,除非你正在做一些简单的事情,比如消除重复

缓存,缓存大小 另一个想法是缓存所有正则表达式并在某个地方编译一次,然后更改
Regex.CacheSize
的大小以查看是否有帮助。默认值为15,但您已超过该值

更多信息
关于实例化和编译表达式一次的注释是有效的,即使没有那么大的注释。还有其他建议。

确保使用
RegexOptions.Compiled
标志在循环外部初始化Regex。同时尽可能多地从循环中移除。如果您可以逐行工作,请尝试这样做,而不是搜索一个巨大的50-60KB字符串。@AeroX-我不是。您可以检查示例代码以获取参考。您在哪里创建了多少次此类实例?它不是静态的,正则表达式在实例创建时就被初始化了。这是低效的。正则表达式本身也很可能(更多?)需要优化。对每个正则表达式匹配进行计时,以查看是否存在需要异常长时间才能匹配(或无法匹配)的正则表达式。像这样的问题通常是由于。嘿-请检查提供的示例代码。我不认为我在做任何疯狂的事情。也许,用正则表达式解析HTML是个坏主意?;-)我确信问题在于某些正则表达式导致了巨大的回溯。调试您的表达式,并检查执行哪里出错。修正模式。重复一遍。请特别注意,.*就是罪魁祸首。ThanksI想补充一点,我怀疑在循环中构造正则表达式,甚至不使用
RegexOptions.Compiled
作为C#用
Regex.CacheSize
缓存正则表达式会产生重大问题,所以只要您有相对少量的正则表达式,实际上它应该与@derakantrican差不多,随着最新的发展,.NET正则表达式变得更加稳定,不太容易出现灾难性回溯等问题。这个6年前的答案反映了我们在以前的工作中遵循的最佳实践。