我正在尝试使用多行正则表达式来匹配给定源字符串中的所有通配符。这些字符串可能超过 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/