使用包含(?:。| \ s)*的模式进行正则表达式搜索?需要越来越长的时间

时间:2015-07-08 13:13:00

标签: java regex

我的正则表达式需要越来越长的时间来匹配(第5次约30秒),但需要应用大约500轮比赛。 我怀疑是灾难性的回溯。 请帮忙!如何优化此正则表达式:

String regex = "<tr bgcolor=\"ffffff\">\\s*?<td width=\"20%\"><b>((?:.|\\s)+?): *?</b></td>\\s*?<td width=\"80%\">((?:.|\\s)*?)(?=(?:</td>\\s*?</tr>\\s*?<tr bgcolor=\"ffffff\">)|(?:</td>\\s*?</tr>\\s*?</table>\\s*?<b>Tags</b>))";
编辑:因为不清楚(我的不好):我试图获取一个html格式的文档,然后通过提取两个搜索组并在之后添加格式化来重新格式化。

1 个答案:

答案 0 :(得分:2)

交替(?:.|\\s)+?非常低效,因为它涉及太多的回溯。

基本上,此模式的所有变体都非常低效:(?:.|\s)*?(?:.|\n)*?(?:.|\r\n)*?以及贪婪的对应物((?:.|\s)*(?:.|\n)*(?:.|\r\n)*)。 (.|\s)*?可能是最糟糕的。

<强>为什么吗

两个备选方案.\s可能匹配同一位置的相同文本,两者至少匹配常规空格。请参阅this demo完成3555步骤,.*? demo(使用s修饰符)完成1335步。

Java中的(?:.|\n)*? / (?:.|\n)*等模式经常导致Stack Overflow issue,这里的主要问题与使用与char匹配的交替(已经单独导致回溯)有关char,然后使用未知长度的量词修改组。虽然一些正则表达式引擎可以应对这种并且不会抛出错误,但是这种类型的模式仍然会导致速度减慢并且不建议使用(仅在ElasticSearch Lucene正则表达式引擎中(.|\n)是匹配任何char的唯一方法)。

<强>解决方案

如果要匹配任何字符(包括空格和正则表达式),请使用

进行匹配
[\\s\\S]*?

或使用(?s)(或Pattern.DOTALL Matcher选项启用单线模式)并使用.(例如(?s)start(.*?)end)。

注意:要操作HTML,请使用专用解析器,例如jsoup。以下是讨论Java HTML parsers的SO帖子。