【发布时间】:2013-06-30 03:15:04
【问题描述】:
在最近阅读了一种被称为“灾难性回溯”的现象后,似乎我自己的正则表达式模式正在导致某种 CPU 问题。我使用这个表达式来扫描 100k-200k 个字符的大型 HTML 字符串。该模式匹配 IP:port 格式的 IP 地址(例如 1.1.1.1:90)。模式如下:
private static Regex regIp = new Regex(@"(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\." +
@"(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4]" +
@"[0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\.(25[0-5]|2[0-4][0-9]|[0-1]{1}" +
@"[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])\:[0-9]{1,5}",
RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant);
表达式使用如下:
MatchCollection matchCol = regIp.Matches(response);
foreach (Match m in matchCol)
{
doWorkWithMatch(m);
}
通过这个正则表达式模式运行大约 100 个字符串后,它开始阻塞计算机并使用 99% 的 CPU。有没有更合乎逻辑的方式来构造这个表达式以减少 CPU 使用率并避免回溯?我不确定是否会发生回溯,或者是否只是同时执行正则表达式评估的线程过多的问题 - 欢迎所有输入。
【问题讨论】:
-
不要试图用 Regex 解析像 HTML 这样的不规则语言 - 这就是疯狂的方式。不要这样做。永远不会。寻找另一种方式。加入修道院。拿起钩针。除了这个!
-
用正则表达式解析 HTML 是不可能的,除非在非常特殊的情况下。我只是建议你找到一种不同的方法,所以如果将 HTML 解析为文档不适合你,请使用不同的方法。
-
看看Html Agility Pack - 我从未使用过它,但我在尝试使用 .NET 解析 HTML 时曾多次看到它推荐。
-
@Tim 给定 op 想要匹配的模式,正则表达式是正确的选择
-
正则表达式非常适合这个应用程序,因为您根本不关心语言的结构。如果您的搜索要求依赖于 html 的结构,Mike 的观点是有效的。语言在您的应用程序中毫无意义。