正则表达式中的 \z 和 \Z 之间有什么区别,何时以及如何使用它?

2022-09-01 01:37:04

http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html

\Z  The end of the input but for the final terminator, if any
\z  The end of the input

但这在实践中意味着什么呢?当我使用 \Z 或 \z 时,你能给我一个例子吗?

在我的测试中,我认为这将返回true并返回false。但实际上两者都返回 false。错误在哪里?"StackOverflow\n".matches("StackOverflow\\z")"StackOverflow\n".matches("StackOverflow\\Z")


答案 1

即使 并且仅在字符串的末尾匹配(当插入符号和美元在嵌入的换行符处匹配的选项关闭时),也有一个例外。如果字符串以换行符结尾,则 和 将在该换行符之前的位置匹配,而不是在字符串的最末尾匹配。\Z$\Z$

这个“增强功能”是由Perl引入的,并被许多正则表达式风格复制,包括Java,.NET和PCRE。在Perl中,从文件中读取行时,生成的字符串将以换行符结尾。从带有文本“joe”的文件中读取一行将生成字符串 joe\n。当应用于此字符串时,两者和将匹配“joe”。^[a-z]+$\A[a-z]+\Z

如果只想在字符串的绝对末尾进行匹配,请使用(小写 z 而不是大写 Z)。 与 joe\n 不匹配。 在换行符之后匹配,该换行符与字符类不匹配。\z\A[a-z]+\z\z

http://www.regular-expressions.info/anchors.html

我阅读此内容的方式应该返回 false,因为您的模式不包含换行符。"StackOverflow\n".matches("StackOverflow\\z")

"StackOverflow\n".matches("StackOverflow\\z\\n") => false
"StackOverflow\n".matches("StackOverflow\\Z\\n") => true

答案 2

刚刚检查过。看起来当调用 Matcher.matches() 时(就像在代码中一样,在幕后),\Z 的行为类似于 \z。但是,当调用 Matcher.find() 时,它们的行为与预期不同。以下返回 true:

Pattern p = Pattern.compile("StackOverflow\\Z");
Matcher m = p.matcher("StackOverflow\n");
System.out.println(m.find());

如果将 \Z 替换为 \z,则返回 false。

我发现这有点令人惊讶...