正则表达式挂起 - Java 匹配器

问题描述 投票:0回答:3

字符串:

水族、月桂基聚氧乙烯醚硫酸钠、月桂基硫酸钠、聚二甲基硅氧烷、椰油酰胺MEA、碳酸锌、乙二醇二硬脂酸酯、氯化钠、吡啶硫酮锌、二甲苯磺酸钠、鲸蜡醇、香料、瓜尔胶羟丙基三甲基氯化铵、硫酸镁、苯甲酸钠、月桂基聚氧乙烯醚硫酸铵、氢氧化碳酸镁、芳樟醇、丁基苯基甲基丙醛、柠檬烯、羟基异己基 3-环己烯甲醛、苯甲醇、己基肉桂醛、香茅醇、生育酚乙酸酯、石蜡液、聚萘磺酸钠、CI 19140、DMDM 乙内酰脲、CI 15510、甲基氯异噻唑啉酮、二钠EDTA、EDTA四钠, 甲基异噻唑啉酮。

当前正则表达式:

System.out.println(string.matches("([\\W]*\\b[A-Z\\d]\\w+\\b[\\W]*)+"));

Java 应用程序挂起。我在正则表达式中找不到错误。通过谷歌搜索,我发现这可以称为“灾难性回溯”!? 如果字符串仅包含大写单词,则正则表达式应与字符串匹配 例如,如果 1 个单词是小写的,则不应与其匹配。

java regex string
3个回答
1
投票

我建议您按单词拆分输入字符串,然后进行模式匹配,更简单:如果您只想测试每个单词的第一个字母是否大写,则不要进行模式匹配,例如:

for (String s : string.split("\\W")) {
  if (s.charAt(0) < 'A' || s.charAt(0) > 'Z') {
    return false;
  }
}

对我来说听起来快得多(如果需要的话,你甚至可以得到失败的单词)。


0
投票

也许你的想法是

String regex = "([A-Z][\\d\\w]+( [A-Z][-\\d\\w]+)*, )*[A-Z][-\\d\\w]+( [A-Z][-\\d\\w]+)*\\.";
System.out.println(string.matches(regex));

返回真。

正则表达式的问题在于它过于复杂。在获得

true
之前添加表达式的缺点是它可能会匹配您没有想到的内容。

Random rand = new Random();
while(true) {
    byte[] bytes = new byte[40];
    rand.nextBytes(bytes);
    for (int i = 0; i < bytes.length; i++) bytes[i] &= 0x7F;
    String string = new String(bytes, 0);
    if (string.matches("([\\W]*\\b[A-Z\\d]\\w+\\b[\\W\\d]*)+"))
        System.out.println(string);
}

打印诸如

之类的东西
"^;%XX`'SwJ|[*4"*0C<Tgbom_. \^
{PvU_y9aJSm?08EL(   NpfA9a[:$YbN8VTtMk
;![`LR7Yy\AO5PZ@X4}GajC<*XvKE11
8l5W6*IDNH[9C'@.>7`LHsCN*,{26O}
EFJ5MBVxi%W_t6v54EmLmgjFvqyYh\<"
+7]|ULh2[MT`Yx{MKH4N
'8p!2mf

而我给出的表达式匹配

KfhBuGv7, S3.
IWzu, XHop4Z.
LJbXfrd, PdR.
V2dxQV, LA9z.
HKf37cy0, TS.
RAw2E5a, Ajs.
Up-, GPQ7 I_.

0
投票

遵循我一直在使用的这些提示,以避免 Regex 挂起。

  1. 如果可能,请避免在程序中使用Regex。相反,您应该手动创建一个方法或函数来为您完成所有这些事情,这比使用 Regex 更快,后者在给您预期的结果之前在内部执行繁重的编译操作。

  2. 避免在嵌套运行循环内执行繁重的Regex操作。相反,您应该将这些循环分解为多个阶段。 例如:

int count = 0;
int stage = 1;
while (true) {
    if (stage == 1) {
        // Perform first loop operations...
        // then move to stage 2...
        stage = 2;
        //continue;
    }
    if (stage == 2) {
        // Perform second loop operations...
        // Where you can call your Regex functions if you like...
        count++;
        if (count > 2) {
            stage = 3;
            //continue;
        }
    }
    if (stage == 3) {
        // Right here you may decide to terminate the loop completely...
        break;
        // NOTE: Failure to call break; when done with the loop will cause this loop to run as an infinite loop!
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.