下面的正则表达式在测试here时可以成功工作,但是当我尝试将其实现到Java代码中时,它不会返回匹配。它使用负前视来确保MAIN LEVEL
和Bedrooms
之间不会出现换行符。为什么它在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
2条答案
按热度按时间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
在大多数情况下足够了",并且您可以可靠地将其用于面向家庭级用户的系统。然而,一些(罕见的)操作系统,通常是工业级的东西,比如服务器,可能会使用
CR
、LF-CR
,或者完全是其他的东西,这就是为什么第二种方法有这么多的字符,所以如果你 * 需要 * 代码与***每个***系统兼容,你将 * 需要 * 第二种方法,或者最好是第三种方法。1.下面是一个有用的方法来测试你的模式失败的地方:
fzwojiic2#
这是行分隔符。您正在查找
\n
,但您的文件实际上使用\r\n
。如果您运行的是Java 8,则可以将代码中的每个\\n
更改为\\R
(通用行分隔符)。对于Java 7或更早版本,请使用\\r?\\n
。