关于作者:Vlad Mihalcea是一个专注于软件集成,高可扩展性和并发编程挑战的软件架构师


我从来没有想到我可以看到一个差劲的正则式造成一台服务器没有响应。但它偏偏就在我们的一个服务器上面发生了,结果导致了它毫无响应。


假设我们在解析一些外部汽车经销商的信息。我们想在各种各样的输入中找到那些带”no air conditioning”的汽车,同时不要匹配那些诸如”mono air conditioning”的模式。


那个搞挂我们服务器的正则式类似于这样:


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 ));


两分钟后,这个测试还没有停止并且一个CPU核已经满负载运行了。


图片


首先,我们是在整个输入数据上使用matches方法的,所以不需要开始(^)和结束($)匹配符。其次,由于输入字符串中存在换行符,我们必须让正则式运行在多行模式下:


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


让我们看一看不同版本的正则式的行为:


图片


为什么不用String.indexOf()


尽管它应该比正则式快很多,但我们仍需要考虑字符串开始的情况,例如一些像”mono air conditioning”的模式;以及用制表符或多个空格符分开的输入。像这样自定制的实现可能会快一些,但都缺少灵活性而且需要更多的时间去实现。


结论


正则式是模式匹配的利器,但你不应该随心所欲的使用它。因为很小的改变可能带来很大的不同。第一个正则式事与愿违的原因是由于catastrophic backtracking。这是一个每位开发者在写正则式之前都应当注意的一个现象。


更多相关文章

  1. 说说 Java 代理模式
  2. 设计模式的六大原则
  3. 010. 正则表达式匹配 | Leetcode题解
  4. Jquery Validate 正则表达式实用验证代码常用的
  5. 使用Selectize和Ajax时,在Bootstrap模式中显示Rails错误消息
  6. 当AJAX响应来自PHP文件时,如何显示以消息为中心的加载器图像&防止
  7. Twitter在模式窗口中引导数据表程序
  8. jquery-validation-1.13.1 自定义验证正则
  9. 有没有办法强制Chrome在OSX上以演示模式打开?

随机推荐

  1. TableLayout设置行与行之间的分割线
  2. Android 6.0及运行时权限处理
  3. [置顶] Android 各类功能效果源代码集合
  4. Android设置android:clipChildren达到的
  5. android的大好时光结束进行时
  6. 王家林的81门一站式云计算分布式大数据&
  7. Android串口Serial服务解析
  8. Android技术专家 高焕堂 推荐这本书
  9. Android音乐播放器系列讲解之一
  10. Android的ps命令介绍和技巧