破坏服务器的正则表达式

我从没想过我会因为正则表达式匹配器不正确而导致服务器无响应,但这只是发生在我们的一项服务中,导致服务器无响应。

假设我们解析了一些外部经销商的汽车信息。 我们正在尝试在所有可用的输入模式中找到所有那些“无空调”的汽车(但没有诸如“单空调”之类的匹配模式)。

破坏我们服务的正则表达式如下:

String TEST_VALUE = "ABS, traction control, front and side airbags, Isofix child seat anchor points, no air conditioning, electric windows, \r\nelectrically operated door mirrors";
double start = System.nanoTime();
Pattern pattern = Pattern.compile("^(?:.*?(?:\\s|,)+)*no\\s+air\\s+conditioning.*$");
assertTrue(pattern.matcher(TEST_VALUE).matches());
double end = System.nanoTime();
LOGGER.info("Took {} micros", (end - start) / (1000 ));

2分钟后,该测试仍在运行,并且一个CPU内核完全过载。

正则表达式超载

首先, matchs方法使用整个输入数据,因此我们不需要start(^)或end($)分隔符,并且由于输入字符串中的换行符,我们必须指示Regex Pattern在其中进行操作MULTILINE模式:

Pattern pattern = Pattern.compile("(?:.*?(?:\\s|,)+)*no\\s+air\\s+conditioning.*?", Pattern.MULTILINE);

让我们看看此正则表达式的多个版本的行为:

正则表达式 持续时间[微秒] 观察
“((?:。*?(?:\\ s |,)+)*否\\ s + air \\ s +调节。*?” 35699.334 这太慢了
“((?:。*?(?:\\ s |,)+)?no \\ s + air \\ s + condition。*?” 108.686 非捕获组不需要一个或多个(+)乘数,因此我们可以将其替换为零或一个(?)
“(?:。*?\\ b)?no \\ s + air \\ s + condition。*?” 153.636 它比前一个输入更多的输入数据,后者仅使用空格(\ s)和逗号(,)分隔匹配的模式
“ \\ bno \\ s + air \\ s + condition” 78.831 查找匹配快得多,我们只对这种模式的首次出现感兴趣。

为什么不使用

尽管这比使用正则表达式要快得多,但我们仍然必须考虑字符串的开头,模式标记之间的模式,例如“单空调”,制表符或多个空格字符。 这样的自定义实现可能更快,但灵活性较差,需要更多时间来实现。

结论

正则表达式是用于模式匹配的很好的工具,但是您千万不要认为它是理所当然的,因为小的更改可能会产生很大的差异。 第一个正则表达式起反作用的原因是灾难性的回溯 ,这是每个开发人员在开始编写正则表达式之前都应意识到的现象。

参考: Vlad Mihalcea博客博客上的正则表达式破坏了我们的JCG合作伙伴 Vlad Mihalcea 的服务器

翻译自: https://www.javacodegeeks.com/2014/02/the-regex-that-broke-a-server.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值