负面的前瞻性正则表达式不适用于Java

时间:2015-12-27 04:39:15

标签: java regex pattern-matching negative-lookahead

以下正则表达式在测试here时成功运行,但是当我尝试将其实现到我的Java代码中时,它不会返回匹配项。它使用否定前瞻来确保MAIN LEVELBedrooms之间不会出现换行符。为什么它不能用Java?

正则表达式

^\s*\bMAIN LEVEL\b\n(?:(?!\n\n)[\s\S])*\bBedrooms:\s*(.*)

爪哇

pattern = Pattern.compile("^\\s*\\bMAIN LEVEL\\b\\n(?:(?!\\n\\n)[\\s\\S])*\\bBedrooms:\\s*(.*)");
    match = pattern.matcher(content);      
    if(match.find())
    {
        //Doesn't reach here
        String bed = match.group(1);
        bed = bed.trim();
    }

content只是从文本文件中读取的字符串,其中包含上面链接的演示中显示的确切文本。

File file = new File("C:\\Users\\ME\\Desktop\\content.txt"); 
 content = new Scanner(file).useDelimiter("\\Z").next();

更新

我将代码更改为包含多行修饰符(?m),但它打印出“null”。

pattern = Pattern.compile("(?m)^\\s*\\bMAIN LEVEL\\b\\n(?:(?!\\n\\n)[\\s\\S])*\\bBedrooms:\\s*(.*)");
    match = pattern.matcher(content);
    if(match.find())
    {   // Still not reaching here
        mainBeds=match.group(1);
        mainBeds= mainBeds.trim();
    }
  System.out.println(mainBeds);     // Prints null

2 个答案:

答案 0 :(得分:4)

问题:

正如Alan Moore's answer中所述,文件中使用的Line-Separators格式(\r\n)与您的模式指定的格式(\n)不匹配:

原始代码:
Pattern.compile("^\\s*\\bMAIN LEVEL\\b \\n (?:(?! \\n\\n {{ 1}}

注意:我在的第二项中解释)[\\s\\S])*\\bBedrooms:\\s*(.*)");\r代表的内容,以及\n\r\n之间的背景和差异附注“部分。

解决方案:

  1. 大多数/所有Java版本:
    您可以使用\n来匹配这两种格式,在大多数情况下足够

  2. 大多数/所有Java版本:
    您可以使用\r?\n来匹配“任何Unicode换行序列”

  3. Java 8及更高版本:
    您可以使用Linebreak Matcher (\R)。它等同于第二种方法(上面),并且只要可能(Java 8或更高版本), 这是推荐的方法

  4. 结果代码(第3种方法):
    \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029] Pattern.compile("^\\s*\\bMAIN LEVEL\\b \\R (?:(?! {{ 1}}

    旁注:

    1. 您可以将\\R\\R替换为更具可读性的)[\\s\\S])*\\bBedrooms:\\s*(.*)");

    2. 存在不同格式的换行符,并在不同的系统中使用,因为早期的操作系统继承了机械打字机的“换行逻辑”,如打字机。

      代码中的\\R\\R代表 回车 ,又名 \\R{2} 。这背后的想法是将键入光标返回到行的开头。

      代码中的\r代表 换行 ,又名 CR 。这背后的想法是将键入光标移动到下一行。

      最常见的换行符格式为\nLF),主要由Windows使用;和CR-LF\r\n),大多数类UNIX系统使用。这就是LF 足够在大多数情况下”的原因,您可以将其可靠地用于家庭级用户的系统。

      然而 ,某些(罕见)操作系统(通常用于服务器等工业级产品)可能会使用\n\r?\n或完全不同的东西,这就是为什么第二种方法中包含如此多的字符,所以如果你需要代码与 每个 系统兼容,“你将需要第二种,或者最好是第三种方法。

    3. 这是测试模式失败的有用方法:

      CR

答案 1 :(得分:2)

它是行分隔符。您正在寻找\n,但您的文件实际上使用的是\r\n。如果您正在运行Java 8,则可以将代码中的每个\\n更改为\\R(通用行分隔符)。对于Java 7或更早版本,请使用\\r?\\n