如何选择空格模式?

6
Oracle Pattern documentation中,有三种不同的模式用于匹配空格的描述:
  1. \s
  2. \p{Space}
  3. \p{javaWhitespace}
我想知道每个模式的具体性质以及如何选择正确的模式。 我刚注意到\p{javaWhitespace}包含更多类型的空格。

这取决于哪种方式对您来说最清晰,以及您需要它用于什么。您需要将“更多空格类型”视为空格还是不视为空格? - Peter Lawrey
是的,我想使用它来分隔句子中的单词。 - alain.janinm
3个回答

7

\s 是指定“空格字符”的最短且不太可移植的选项。虽然将Java代码移植到其他语言很少见,但更多是将一种正则表达式引擎的语法知识移植到另一个上。有许多使用Perl语法的正则表达式引擎,因此对于相同语法的解释差异(例如\s),会让程序员感到困惑。

除了空格(ASCII 32)、换行符(\n,ASCII 10)、水平制表符(\t,ASCII 9)、回车符(\r,ASCII 13)和换页符(\f,ASCII 12)之外,在不同引擎之间并没有达成一致,关于什么是“空格字符”。

  • Java, POSIX (ASCII):还包括垂直制表符(ASCII 11)。Java 在这里似乎遵循 POSIX 标准。

  • JavaScript(版本 5.1):根据规范(逐字逐句),除了 5 种常见的字符外,还包括:

    • Unicode 类别Zs(分隔符/空格)\u2028(行分隔符)、\u2029(段落分隔符)。它基本上包括类别 Z(分隔符)下的所有字符。

      实际上,\u2028 是类别 Zl(分隔符/行) 的唯一成员,而 \u2029 是类别 Zp(分隔符/段落) 的唯一成员。从措辞上看,当前版本的规范可能排除了对那两个类别的任何进一步扩展。

    • 垂直制表符 \v
    • 字节序标记 a.k.a. 零宽不换行空格 \ufeff
  • Perl、PCRE(ASCII 模式):从 Perl 5.18 开始作为实验添加了垂直制表符 \v。在 5.18 之前,它只匹配 5 种常见的字符。

  • Perl(Unicode 模式):除了 5 种常见的字符外

    • Unicode 类别 Z(分隔符)
    • 从 Perl 5.18 开始作为实验添加了垂直制表符 \v
    • NEXT LINE(NEL)\u0085
    • 蒙古语元音分隔符 \u180e
  • .NET(默认):除了 5 种常见的字符外

    • Unicode 类别 Z(分隔符)
    • 垂直制表符 \v
    • NEXT LINE(NEL)\u0085
  • Java(Unicode):从 Java 7 开始,Pattern 类包括一个新标志UNICODE_CHARACTER_CLASS,使得预定义字符类POSIX 字符类符合 Unicode Regular Expression 技术标准#18。当启用该标志时,预定义字符类和相应的POSIX 字符类将变得等效(匹配相同的内容)。

    字符列表与 .NET 相同。

那已经足以让人发疯了!


\p{Space} 是更为“稳定”的选项,因为它在默认模式下遵循POSIX标准UNICODE_CHARACTER_CLASS中的Unicode技术标准#18:Unicode正则表达式

如果您使用POSIX字符类,则符合POSIX标准的实现将在ASCII模式下具有相同的行为,在遵循建议的Unicode正则表达式引擎中,在Unicode模式下也会有(几乎)相同的行为。

在Java中,无论标志如何,\s\p{Space}是等效的。如果您在Java中使用\s,您可以确信您正在遵循某些标准/建议。只是这事实并没有向大多数程序员宣布。


\p{isJavaWhitespace}可以匹配符合Java的定义的空格。该函数名称极其误导。


此答案已添加到Stack Overflow正则表达式FAQ,位于“字符类”。 - aliteralmind

5

我更喜欢使用第一个。

  • 它很简洁
  • 在许多其他语言以及正则表达式理论中都是相同的符号表示法
  • \p{javaWhitespace} 包括文件分隔符组分隔符等,请参见这里。不必要地使用它可能会使其他人感到困惑。
  • 通常情况下,我会期望另一个程序员知道\s是什么,而我会期望他们仔细检查\p{javaWhitespace}的确切定义。这并无益处,会降低代码清晰度,并增加调试时不必要的负担。

好的,谢谢!在我的情况下,使用\p{javaWhitespace}对于开发人员来说是透明的,因为我正在使用java.util.Scanner来迭代字符串中的单词,并且它是默认分隔符。所以我想知道是否应该改用.useDelimiter("\\s+") - alain.janinm

1

除非你有特定的原因使用其他选项,否则我建议保持简单,使用\s


жЙАдї•\sеП™жШѓеЖЩ\p{Space}зЪДдЄАзІНжЫізЃАеНХзЪДжЦєеЉПеРЧпЉЯ - alain.janinm

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