Java 正则表达式库是否针对任何字符 .* 进行优化?

2024-01-13

我有一个用于匹配正则表达式的包装类。显然,您将正则表达式编译为Pattern像这样。

Pattern pattern = Pattern.compile(regex);

但假设我用了一个.*指定任意数量的字符。所以它基本上是一个通配符。

Pattern pattern = Pattern.compile(".*");

该模式是否优化为始终返回 true 并且不真正计算任何内容?或者我应该让我的包装器实现该优化?我这样做是因为我可以轻松地在一个进程中处理数十万个正则表达式操作。如果正则表达式参数为空,我将其合并为.*


在你的情况下,我可以使用所有格量词来避免任何回溯:

.*+

Java 模式匹配引擎有多种优化可供使用,并且可以自动应用它们。

这是什么克里斯蒂安·莫卡努 (Cristian Mocanu) 在他的著作中写道优化 Java 中的正则表达式 http://www.javaworld.com/article/2077757/core-java/optimizing-regular-expressions-in-java.html?page=3关于类似的案例.*:

Java 正则表达式引擎无法优化表达式.*abc.*。我预计它会搜索abc在输入字符串中并很快报告失败,但事实并非如此。在同一输入字符串上,使用String.indexOf("abc")比我改进的正则表达式快三倍。看来,只有当已知字符串位于其开头或位于其中的预定位置时,引擎才能优化此表达式。例如,如果我将表达式重写为.{100}abc.*引擎的匹配速度会快十倍以上。为什么?因为现在强制字符串abc位于字符串内的已知位置(它之前应该正好有一百个字符)。

一些来自同一来源的 Java 正则表达式优化提示 http://www.javaworld.com/article/2077757/core-java/optimizing-regular-expressions-in-java.html?page=2:

  • 如果正则表达式包含输入字符串中必须存在的字符串(否则整个表达式将不匹配),引擎有时会首先搜索该字符串,如果没有找到匹配项,则报告失败,而不进行检查整个正则表达式。

  • 自动优化正则表达式的另一种非常有用的方法是让引擎根据正则表达式检查输入字符串的长度与预期长度。例如,表达式\d{100}进行了内部优化,如果输入字符串的长度不是 100 个字符,引擎将报告失败,而不评估整个正则表达式。

  • 不要在分组或交替中隐藏强制字符串,因为引擎将无法识别它们。如果可能的话,指定要匹配的输入字符串的长度也很有帮助

  • 如果您将在程序中多次使用正则表达式,请务必使用以下命令编译该模式Pattern.compile()而不是更直接的Pattern.matches().

  • 另请记住,您可以重复使用Matcher通过调用方法来获取不同输入字符串的对象reset().

  • 谨防交替。正则表达式如(X|Y|Z)他们以行动迟缓而闻名,所以要小心他们。首先,交替的顺序很重要,因此将更常见的选项放在前面,这样可以更快地匹配它们。另外,尝试提取常见模式;例如,而不是(abcd|abef) use ab(cd|ef).

  • 每当您使用否定字符类来匹配其他内容以外的内容时,请使用所有格量词:而不是[^a]*a use [^a]*+a.

  • 不匹配的字符串可能会比包含匹配的字符串更频繁地导致代码冻结。请记住始终首先使用不匹配的字符串测试您的正则表达式!

  • 当心一个已知错误#5050507 http://www.javaworld.com/article/2077757/core-java/optimizing-regular-expressions-in-java.html?page=4#resources(当正则表达式Pattern类抛出一个堆栈溢出错误),如果遇到此错误,请尝试重写正则表达式或将其拆分为多个子表达式并分别运行。后一种技术有时甚至可以提高性能。

  • 使用缓和的贪婪标记代替惰性点匹配(例如(?:(?!something).)*) or 展开循环技术 http://www.softec.lu/site/RegularExpressions/UnrollingTheLoop(今天被否决了,不知道为什么)。

    不幸的是,您不能始终依赖引擎来优化您的正则表达式。在上面的例子中,正则表达式实际上匹配得相当快,但在很多情况下,表达式太复杂,输入字符串太大,引擎无法优化。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 正则表达式库是否针对任何字符 .* 进行优化? 的相关文章

随机推荐