以下正则表达式在测试here时成功运行,但是当我尝试将其实现到我的Java代码中时,它不会返回匹配项。它使用否定前瞻来确保MAIN LEVEL
和Bedrooms
之间不会出现换行符。为什么它不能用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
答案 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
之间的背景和差异附注“部分。
大多数/所有Java版本:
您可以使用\n
来匹配这两种格式,在大多数情况下足够。
大多数/所有Java版本:
您可以使用\r?\n
来匹配“任何Unicode换行序列”。
Java 8及更高版本:
您可以使用Linebreak Matcher (\R
)。它等同于第二种方法(上面),并且只要可能(Java 8或更高版本), 这是推荐的方法 。
结果代码(第3种方法):
\u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]
的 Pattern.compile("^\\s*\\bMAIN LEVEL\\b
强> \\R
的 (?:(?!
强> {{ 1}}
您可以将\\R\\R
替换为更具可读性的)[\\s\\S])*\\bBedrooms:\\s*(.*)");
。
存在不同格式的换行符,并在不同的系统中使用,因为早期的操作系统继承了机械打字机的“换行逻辑”,如打字机。
代码中的\\R\\R
代表 回车 ,又名 \\R{2}
。这背后的想法是将键入光标返回到行的开头。
代码中的\r
代表 换行 ,又名 CR
。这背后的想法是将键入光标移动到下一行。
最常见的换行符格式为\n
(LF
),主要由Windows使用;和CR-LF
(\r\n
),大多数类UNIX系统使用。这就是“LF
足够在大多数情况下”的原因,您可以将其可靠地用于家庭级用户的系统。
然而 ,某些(罕见)操作系统(通常用于服务器等工业级产品)可能会使用\n
,\r?\n
或完全不同的东西,这就是为什么第二种方法中包含如此多的字符,所以如果你需要代码与 每个 系统兼容,“你将需要第二种,或者最好是第三种方法。
这是测试模式失败的有用方法:
CR
答案 1 :(得分:2)
它是行分隔符。您正在寻找\n
,但您的文件实际上使用的是\r\n
。如果您正在运行Java 8,则可以将代码中的每个\\n
更改为\\R
(通用行分隔符)。对于Java 7或更早版本,请使用\\r?\\n
。