Java - 多行正则表达式大字符串性能不佳

标签 java regex performance

我正在尝试使用多行正则表达式来匹配给定源字符串中的所有通配符。这些字符串可能超过 70,000 行,并且每个项目由换行符分隔。

我当前的正则表达式似乎经历了巨大的处理时间,我只能假设这是因为它可能构造不良且效率低下。如果我在手机上执行代码,它似乎会永远运行。

我当前的正则表达式:

(?im)(?=^(?:\*|.+\*$))^(?:\*[.-]?)?(?:(?!-)[a-z0-9-]+(?:(?<!-)\.)?)+(?:[a-z0-9]+)(?:[.-]?\*)?$

有效通配符示例:

*test.com
*.test.com
*test
test.*
test*
*test*

我用以下方法编译模式:

private static final String WILDCARD_PATTERN = "(?im)(?=^(?:\\*|.+\\*$))^(?:\\*[.-]?)?(?:(?!-)[a-z0-9-]+(?:(?<!-)\\.)?)+(?:[a-z0-9]+)(?:[.-]?\\*)?$";
private static final Pattern wildcard_r = Pattern.compile(WILDCARD_PATTERN);

我寻找匹配项:

// Wildcards
while (wildcardPatternMatch.find()) {
    String wildcard = wildcardPatternMatch.group();
    myProperty.add(new property(wildcard, providerId));
    System.out.println(wildcard);
}

我可以进行任何更改来改进/优化正则表达式吗?或者我是否需要查看运行 .replaceAll在进行正则表达式匹配之前多次删除所有困惑?

最佳答案

您需要的模式是

(?im)^(?=\*|.+\*$)(?:\*[.-]?)?[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*(?:[.-]?\*)?$

请参阅regex demo

要点:

  • 第一个前瞻应该在 ^ 之后。如果是之前,则在字符串中每个字符之前和之后进行检查。一旦是^之后,仅在一行开头执行一次
  • (?:(?!-)[a-z0-9-]+(?:(?<!-)\.)?)+这一部分虽然很短,但实际上正在扼杀性能,因为 (?:(?<!-)\.)?是可选模式,整个模式减少为 (a+)+ ,一种已知的模式类型,如果其右侧还有其他子模式,则会导致灾难性回溯。你需要打开它,最好的“线性”方式是 [a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)* .

剩下的就OK了。

详细信息

  • (?im) - 不区分大小写和多行修饰符
  • ^ - 一行的开头
  • (?=\*|.+\*$) - 字符串应以 * 开头或结尾
  • (?:\*[.-]?)? - 匹配 * 的可选子字符串和可选的.或 -` 字符
  • [a-z0-9](?:[a-z0-9-]*[a-z0-9])? - 字母数字字符后跟任何 0+ 字母数字字符的可选序列或/和 -后跟字母数字字符
  • (?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)* - 0 个或多个点序列,后跟上述模式
  • (?:[.-]?\*)? - 与可选 . 匹配的可选子字符串或 - char and then a *`
  • $ - 行尾。

关于Java - 多行正则表达式大字符串性能不佳,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51559537/

相关文章:

java - Android 应用程序 - onCreateView 中的 HttpURLConnection

Java 在不使用数组的情况下反转 int 值

java - 文件在 Java Jersey API 中下载两次

regex - 如何在脚本中使用正则表达式来 gzip 日志文件

regex - Clojure 用正则表达式替换字符串

c++ - 与相应的 cpp 代码相比,为什么这个 bash 代码这么慢?

php - PHP Globals 的安全替代品(良好编码实践)

java - 在 JCR 2 中将 inputStream 读入节点属性的正确方法是什么?

当正则表达式的第一个字符是 * 时,Java PatternSyntaxException

performance - VBS vs PowerShell : Which is lighter?