regex 负前瞻正则表达式在Java中不起作用

ycl3bljg  于 2022-12-30  发布在  Java
关注(0)|答案(2)|浏览(157)

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

    • 正则表达式**

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

    • java **
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
e37o9pze

e37o9pze1#

问题:

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

    • 原始代码:**

一个三个一个***一个四个一个***一个五个一个***一个六个一个***一个七个一个
注意:我将在 "旁注" 部分的第二项中解释\r\n代表什么,以及\r\n\n之间的上下文和区别。

溶液:

1.* * 大多数/所有Java版本:**
您可以使用\r?\n来匹配这两种格式,这在大多数情况下已经足够了。
1.* * 大多数/所有Java版本:**
您可以使用\u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]来匹配 "任何Unicode换行符序列"
1.* * Java 8及更高版本:**
您可以使用换行符匹配器(\R)。它等效于第二种方法(上面),并且只要可能(Java 8或更高版本),这是推荐的方法

    • 结果代码(第三种方法):**

x 1米15英寸x***x 1米16英寸x***x 1米17英寸x***x 1米18英寸x***x 1米19英寸x

旁注:

1.您可以将\\R\\R替换为\\R{2},这样可读性更强。
1.不同的换行符格式存在于不同的系统中,因为早期的操作系统继承了机械打字机(如打字机)的“换行符逻辑”。
代码中的\r表示一个***回车符***,又名***CR***,其背后的思想是将输入光标返回到行首。
代码中的\n表示一个换行符***,又名***LF*,其背后的思想是将输入光标移动到下一行。
最常见的换行符格式是CR-LF\r\n),主要由Windows使用;和LF\n),用于大多数类UNIX系统。这就是为什么 *"\r?\n在大多数情况下
足够了
"
,并且您可以可靠地将其用于面向家庭级用户的系统。

然而,一些(罕见的)操作系统,通常是工业级的东西,比如服务器,可能会使用CRLF-CR,或者完全是其他的东西,这就是为什么第二种方法有这么多的字符,所以如果你 * 需要 * 代码与***每个***系统兼容,你将 * 需要 * 第二种方法,或者最好是第三种方法。

1.下面是一个有用的方法来测试你的模式失败的地方:

String content = "..."; //Replace "..." with your content.
String patternString = "..."; //Replace "..." with your pattern.
String lastPatternSuccess = "None. You suck at Regex!";
for (int i = 0; i <= patternString.length(); i++) {
  try {
    String patternSubstring = patternString.substring(0, i);
    Pattern pattern = Pattern.compile(patternSubstring);
    Matcher matcher = pattern.matcher(content);
    if (matcher.find()) {
      lastPatternSuccess = i + " - Pattern: " + patternSubstring + " - Match: \n" + matcher.group();
    }
  } catch (Exception ex) {
    //Ignore and jump to next
  }
}
System.out.println(lastPatternSuccess);
fzwojiic

fzwojiic2#

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

相关问题