有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java正则表达式保持处理,但不会抛出任何结果

所以我在学习java中的正则表达式,我想知道为什么我要执行这段代码

String xxx = "(\\s+)?(c:/|c:\\\\|C:\\\\|C:/|c:\\|C:\\))?(\\w+(/|\\\\)?)+(/|\\\\)\\w+.[a-z]+";

String x = "C:\\Users\\esteban\\Desktop\\Java_file_testing\\file3.txt";

    if(x.matches(xxx)) {
        System.out.println("matches");
    }else {

            System.out.println("no match found ");
    }

这会打印出matches,但是当我删除.txt时,没有任何响应,我是不是做错了什么


共 (1) 个答案

  1. # 1 楼答案

    你偶然发现了一个catastrophic backtracking案例

    在编写(\\w+(/|\\\\)?)+时,基本上是在正则表达式中引入(\\w+)+模式。这使得正则表达式引擎有机会以多种方式(使用内部或外部+)匹配同一个字符串——可能的路径数呈指数增长,而且由于引擎在声明失败之前必须尝试所有可能的匹配方式,因此返回值需要花费很长时间

    另外,对你的正则表达式有一些一般性的评论:

    • c:\\|将匹配字符串c:|
    • /|\\\\只是[/\\\\]
    • (\s+)?\s*
    • .是一个需要转义的通配符(“除了换行以外的任何内容”)
    • 对于c/C变体,可以使用[cC]或使整个正则表达式case insensitive
    • 当您不需要实际捕获值时,使用非捕获组(?:...)可以减轻引擎的一些工作

    考虑到这些因素,符合你第一次尝试精神的正则表达式可能是:

    \\s*(?:[cC]:[/\\\\])?(?:\\w+[/\\\\])*\\w+\\.[a-z]+
    

    (?:\\w+[/\\\\])中,字符类[/\\\\]不再是可选的,因此避免了(\\w+)+模式:请参见demo here

    关于灾难性回溯的更多信息,我推荐优秀的(而且有趣!)弗里德尔关于the perl journal主题的文章