我有一个程序在相当长的文本集上运行大量正则表达式(10+)(5-15个文本,每个约1000个单词)
每次完成后我觉得我忘记了某处的Thread.Sleep(5000)。正则表达式真的是处理器重的还是什么?看起来计算机应该在一毫秒内完成这样的任务。
我应该尝试将所有正则表达式分组为一个怪物表达式吗?那会有帮助吗?
由于
编辑:这是一个正在运行的正则表达式:Regex rgx = new Regex(@"((.*(\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*).*)|(.*(keyword1)).*|.*(keyword2).*|.*(keyword3).*|.*(keyword4).*|.*(keyword5).*|.*(keyword6).*|.*(keyword7).*|.*(keyword8).*|.*(count:\n[0-9]|count:\n\n[0-9]|Count:\n[0-9]|Count:\n\n[0-9]|Count:\n).*|.*(keyword10).*|.*(summary: \n|Summary:\n).*|.*(count:).*)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
Regex regex = new Regex(@".*(\.com|\.biz|\.net|\.org|\.co\.uk|\.bz|\.info|\.us|\.cm|(<a href=)).*", RegexOptions.Compiled | RegexOptions.IgnoreCase);
这是非常巨大的,毫无疑问。这个想法是,如果它涉及任何关键字或链接,它将只取出围绕它的整个段落。
答案 0 :(得分:2)
正则表达式不会杀死CPU,正则表达式的作者会这样做。 ;)
但严重的是,如果正则表达式总是像你描述的那样慢,那么就没有人会使用它们。在你开始加载像Compiled
选项之类的银色项目符号之前,你应该回到你的正则表达式,看看它是否可以改进。
它可以。每个关键字都在它自己的分支/替代中,每个分支都以.*
开头,因此每个分支所做的第一件事就是消耗当前段落的剩余部分(即,直到下一个换行的所有内容)。然后它在尝试匹配关键字时开始回溯。如果它回到它开始的位置,下一个分支接管并做同样的事情。
当所有分支都报告失败时,正则表达式引擎会向前突破一个位置并再次遍历所有分支。这是十几个分支,乘以段落中的字符数,乘以段落的数量......我想你明白了。与此正则表达式相比:
Regex re = new Regex(@"^.*?(\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*|keyword1|keyword2|keyword3|keyword4|keyword5|keyword6|keyword7|keyword8|count:(\n\n?[0-9]?)?|keyword10|summary: \n).*$",
RegexOptions.Multiline | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
有三个主要变化:
.*
.*?
,使其变得非贪婪^
模式中添加了行首和行尾锚($
和Multiline
)现在它只对每个段落进行一次匹配尝试(通过或失败),并且它几乎从不回溯。如果我对您的数据有更多了解,我可能会更有效率。例如,如果每个关键字/标记/以字母开头的任何内容,字边界都会产生明显的效果(例如^.*?\b(\w+...
)。
ExplicitCapture
选项使所有“裸”组((...)
)充当非捕获组((?:...)
),在不增加正则表达式混乱的情况下减少开销。如果要捕获令牌,只需将第一个组更改为命名组(例如(?<token>\w+...
)。
答案 1 :(得分:1)
首先,您可以尝试编译选项RegexOptions.Compiled
以下是有关正则表达式效果的好文章:regex-performance
第二个:正则表达式的表现取决于模式: 有些模式比其他模式快得多。你必须尽可能严格地指定模式。
第三个。 我在使用正则表达式方面遇到了一些麻烦。在那种情况下,我使用了string.contains方法。 例如:
bool IsSomethingValid(stging source, string shouldContain, string pattern)
{
bool res = source.Contains(shouldContain);
if (res)
{
var regex = new Regex(pattern, RegexOptions.Compiled);
res = regex.IsMatch(source);
}
return res;
}
如果您向我们提供了脚本示例,我们可能会尝试改进它们。
答案 2 :(得分:1)
永远不要假设您的应用程序运行缓慢的原因和原因。相反,始终衡量它。
使用体面的性能分析器(例如Red Gate's ANTS Performance Profiler - 他们提供14天免费试用版)并实际看到性能瓶颈。
我自己的经验是,我总是错误的是造成糟糕表现的真正原因。在分析的帮助下,我可以找到慢速代码段并调整它们以提高性能。
如果探查器确认您对正则表达式的假设,那么您可以尝试优化它们(通过修改或预编译它们)。
答案 3 :(得分:1)
如果模式不处理大小写...没有ignore case选项。见
Want faster regular expressions? Maybe you should think about that IgnoreCase option...
否则如上所述,但放在这里: