正则表达式模式导致StackoverFlow

时间:2018-11-15 15:20:28

标签: java regex string stack-overflow

我正在JAVA8中的一个项目上,我想从目录或链接中获取HTML文件,并从文件中删除所有样式和脚本标签,然后返回剩余的内容。正在大量文件上反复执行此操作。

现在,这是我用来删除指定标签的两种不同的正则表达式模式。

//remove style tags and style tag content
update = update.replaceAll("<style\\b[^<]*(?:(?!</style>)<[^<]*)*</style>", "");

//remove script tags and script tag content
update = update.replaceAll("<script[\\s\\S]*?>[\\s\\S]*?</script>", "");

这可以工作一段时间,但是似乎偶尔我会遇到java.lang.StackOverflowError

我相信当文件太大时会发生这种情况。我已经进行了一些研究,发现如果在模式中使用"|"会发生这种情况,因为此运算符使用的递归方式可能会占用大量内存,具体取决于遍历的级别数。

我已经设法在不同的测试文件上反复使用这些模式多达1000次。

我的问题是:有人看到这些模式会使用递归吗?还是任何暗示模式本身就是导致溢出的原因?

如果没有,也许我有办法将字符串减小到不会导致此重载的大小。

使用打印语句,似乎在尝试匹配模式时可能发生溢出:

"<script[\\s\\S]*?>[\\s\\S]*?</script>"

另外,有人告诉我可以改用它:

"<script[\\s\\S]+?>[\\s\\S]+?</script>"

因为目前为止还无法预测。此模式可在Regexr中使用,但一旦在JAVA应用程序中实现,则不会提供相同的输出。

这是我收到的堆栈跟踪:

Exception in thread "main" java.lang.StackOverflowError
at java.util.regex.Pattern$Curly.match0(Pattern.java:4252)
at java.util.regex.Pattern$Curly.match(Pattern.java:4236)
at java.util.regex.Pattern$BmpCharProperty.match(Pattern.java:3800)
at java.util.regex.Pattern$Neg.match(Pattern.java:5099)
at java.util.regex.Pattern$GroupHead.match(Pattern.java:4660)
at java.util.regex.Pattern$Loop.match(Pattern.java:4787)
at java.util.regex.Pattern$GroupTail.match(Pattern.java:4719)
at java.util.regex.Pattern$Curly.match0(Pattern.java:4274)

我愿意接受任何建议。谢谢你。

1 个答案:

答案 0 :(得分:0)

我最终结合使用了VGR和MatthewGreen的两个答案。 Re2j解决了我的正则表达式问题,并提高了匹配性能。 -最终,我决定为此减少对正则表达式的依赖,而使用JSoup进行解析,而正则表达式在删除不需要的元素后从文档中提取我想要的东西。