"\n"是垂直空白符吗?也就是说,"\v"是否应该与它匹配?

10

从逻辑上讲,它是这样的(但每当涉及字符编码或区域设置时,逻辑就不相干了)。

perl -e 'print "\n" =~ /\v/ ? "y\n" : "n\n";'

打印出 "y",确实如此。根据

Pattern.compile("\\v").matcher("\n").matches();

在Java中返回false并不是错的。如果没有这篇文章的话,我就不会有任何困惑了。

JDK7中更新的Pattern类拥有一个神奇的新标志:UNICODE_CHARACTER_CLASS,它可以让一切正常工作。

但是我正在使用Java版本"1.7.0_07",该标志存在但似乎完全没有改变任何东西。此外,"\n"不是Unicode的新人,而是一个普通的ASCII字符,所以我真的不知道这个差异可能发生在哪里。也许我做了一些愚蠢的事情,但我看不出来。


3
据我所知,Unicode没有垂直空白属性。这纯粹是Perl构造的,可以匹配以下字符:U+000A、U+000B、U+000C、U+000D、U+0085、U+2028和U+2029。只需使用匹配这些字符的字符类即可。请注意,将内容更加通俗易懂,但不改变原意。 - ikegami
1
@ikegami:有趣。我刚刚发现了这个列表,与您的观点一致。 - maaartinus
此问题已添加到Stack Overflow 正则表达式 FAQ,位于“转义序列”下。 - aliteralmind
请注意,自从Java 8以后,\v表示垂直空白符。 - Haozhun
2个回答

20

Java 7中的java.util.regex.Pattern Javadoc明确提到了不支持\v,并在其“不受此类支持的Perl构造列表”中列出了它。因此,\n不属于Java的“垂直空格”类别;而是因为Java 7没有“垂直空格”类别。相反,Java 7 regex具有一种未记录的功能,可以将\v解释为参考垂直制表符字符U+000B。(这是来自C/C++/Bash等的传统转义序列,但是Java字符串文字不支持它。同样适用于警报/铃声的\a和控制字符X\cX。)

编辑以添加:这已在较新版本的Java中更改。根据Java 8java.util.regex.Pattern Javadoc的说明,\v现在表示“垂直空格字符:[\n\x0B\f\r\x85\u2028\u2029]”。


这是真的,而且这是我自己应该发现的。然而,与许多其他未定义的结构不同,例如 Pattern.compile("\\C"),它不会抛出 PatternSyntaxException。在源代码中,我最终发现它只匹配 U+000B,即“垂直制表符”。听起来很有趣。 - maaartinus
@maaartinus:\v是传统的垂直制表符转义序列(与\n\r等在同一组),尽管Java不支持在字符串字面值中使用它(根据JLS第3.10.6节),但有一些类似的非Java转义序列,java.util.regex.Pattern支持(\a表示警报/响铃,\cX表示控制字符X)。在我看来,这里唯一有趣的事情是文档和实现之间的不匹配:Pattern的Javadoc列出了它应该支持的所有转义序列,包括\n等,但没有提到\v - ruakh
1
就这样吧。我认为我会将它添加到你的答案中,因为这是让我感到困惑的事情。 - maaartinus
如在对 OP 的评论中提到的那样:自 Java 8 开始,支持 \v\V:https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html - IARI
1
@IARI:感谢您提醒。我已经更新了答案并进行了解释。 - ruakh

11

perldoc perlrecharclass提到\v匹配"垂直空白字符"。进一步解释:

"\v"匹配任何被认为是垂直空白字符的字符;这包括平台的回车和换行符(换行符),以及其他几个字符,如下表所列。"\V"匹配任何不被视为垂直空白字符的字符。它们使用平台本地字符集,并且不考虑可能正在使用的任何区域设置。

具体而言,\v在5.16版本中匹配以下字符:

$ unichars -au '\v'           # From Unicode::Tussle
 ---- U+0000A LINE FEED
 ---- U+0000B LINE TABULATION
 ---- U+0000C FORM FEED
 ---- U+0000D CARRIAGE RETURN
 ---- U+00085 NEXT LINE
 ---- U+02028 LINE SEPARATOR
 ---- U+02029 PARAGRAPH SEPARATOR
你可以使用字符类来达到与Perl的\v相同的效果。
当然,这只适用于Perl;我不知道它是否适用于Java。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接