特性類


在 Java 中,可以透過 \p 表示比對的字元具備某特性(Properties),而 \P 表示不具備某特性。例如,如果想要比對小寫字母的話,基本方式是使用字元類 [a-z],然而,Java 的規則表示式方言中,對於那些 Character.isLowerCase 測試結果會是 true 的字元,可以使用 \p{javaLowerCase}

jshell> "a".matches("\\p{javaLowerCase}");
$1 ==> true

jshell> "A".matches("\\p{javaLowerCase}");
$2 ==> false

這些方言稱為 java.lang.Character 類,目前有四個:

  • \p{javaLowerCase}:對應於 Character.isLowerCase 測試結果
  • \p{javaUpperCase}:對應於 Character.isUpperCase 測試結果
  • \p{javaWhitespace}:對應於 Character.isWhitespace 測試結果
  • \p{javaMirrored}:對應於 Character.isMirrored 測試結果

如果你在意撰寫的規則表示式,未來是否易於轉換至其他場合中使用或被閱讀,使用這些方言當然是不建議的,Java 也支援 POSIX 方括號表示式的字元類,例如測試小寫字母:

jshell> "A".matches("\\p{Lower}");
$3 ==> false

jshell> "a".matches("\\p{Lower}");
$4 ==> true

Java 中可用的 POSIX 字元類有:

  • \p{Lower}:小寫字母 [a-z]
  • \p{Upper}:大寫字母 [A-Z]
  • \p{ASCII}:全部的 ASCII [\x00-\x7F]
  • \p{Alpha}:字母 [\p{Lower}\p{Upper}]
  • \p{Digit}:十進位數字 [0-9]
  • \p{Alnum}:字母與數字 [\p{Alpha}\p{Digit}]
  • \p{Punct}:標點符號 !“#$%&'()*+,-./:;<=>?@[]^_`{|}~
  • \p{Graph}:可見字元 [\p{Alnum}\p{Punct}]
  • \p{Print}:可列印字元 [\p{Graph}\x20]
  • \p{Blank}:空白或 Tab [ \t]
  • \p{Cntrl}:控制字元 [\x00-\x1F\x7F]
  • \p{XDigit}:十六進位數字 [0-9a-fA-F]
  • \p{Space}:全部空白字元 [ \t\n\x0B\f\r]

Unicode 特性的支援上,也是使用 \p\P 的方式。

例如〈一般分類特性〉,\p{L} 表示字母(Letter),\p{N} 表示數字(Number)等,可以進一步指定子特性,例如 \p{Lu} 表示大寫字母、\p{Ll} 表示小寫字母:

jshell> "a".matches("\\p{Ll}");
$5 ==> true

jshell> "a".matches("\\p{Lu}");
$6 ==> false

也可以加上 Is,例如 \p{IsL}\p{IsLu} 等,如果是單字元表示特性,例如 \p{L},可以省略 {} 寫為 \pL;也可以使用 \p{general_category=Lu} 或簡寫為 \p{gc=Lu}

有的語言可能會使用多種文字來書寫,例如日語就包含了漢字、平假名、片假名等文字,有的語言只使用一種文字,例如泰文。Unicode 將碼點群組為文字(script)特性上,可以使用 IsHanscript=Hansc=Han 的方式來指定特性,例如測試漢字:

jshell> "林".matches("\\p{IsHan}");
$7 ==> true

對於 Unicode 區塊(block),也就是 Unicode 碼點範圍的指定,可以使用 InCJKUnifiedIdeographsblock=CJKUnifiedIdeographsblk=CJKUnifiedIdeographs,例如,測試中文時常用的 Unicode 碼點範圍為 \u4E00-\u9FFF,也就是 CJK Unified Ideographs 的範圍:

jshell> "林".matches("\\p{InCJKUnifiedIdeographs}");
$8 ==> true

在二元特性的指定上,可以於底下文字前加上 Is:

  • Alphabetic
  • Ideographic
  • Letter
  • Lowercase
  • Uppercase
  • Titlecase
  • Punctuation
  • Control
  • White_Space
  • Digit
  • Hex_Digit
  • Join_Control
  • Noncharacter_Code_Point
  • Assigned

例如:

jshell> "a".matches("\\p{IsLowercase}");
$9 ==> true

預定義與 POSIX 字元類,可以藉由設置旗標 (?U)(對應 Pattern.UNICODE_CHARACTER_CLASS),令其與對應的 Unicode 特性具有一致的表示。例如:

jshell> "林".matches("\\w");
$10 ==> false

jshell> "林".matches("(?U)\\w");
$11 ==> true

\w 原本只用來比對任一 ASCII 字元,設置旗標 (?U) 之後,就可用來比對 Unicode 文字,底下列出設置旗標 (?U) 後的特性對應:

  • \p{Lower}:小寫字元 \p{IsLowercase}
  • \p{Upper}:大寫字元 \p{IsUppercase}
  • \p{ASCII}:全部的 ASCII [\x00-\x7F]
  • \p{Alpha}:字母 \p{IsAlphabetic}
  • \p{Digit}:十進位數字 \p{IsDigit}
  • \p{Alnum}:字母或數字 [\p{IsAlphabetic}\p{IsDigit}]
  • \p{Punct}:標點符號 \p{IsPunctuation}
  • \p{Graph}:可見字元 [^\p{IsWhite_Space}\p{gc=Cc}\p{gc=Cs}\p{gc=Cn}]
  • \p{Print}:可列印字元 [\p{Graph}\p{Blank}&&[^\p{Cntrl}]]
  • \p{Blank}:空白或 Tab [\p{IsWhite_Space}&&[^\p{gc=Zl}\p{gc=Zp}\x0a\x0b\x0c\x0d\x85]]
  • \p{Cntrl}:控制字元 \p{gc=Cc}
  • \p{XDigit}:十六進位數字 [\p{gc=Nd}\p{IsHex_Digit}]
  • \p{Space}:空白字元 \p{IsWhite_Space}
  • \d:十進位數字 \p{IsDigit}
  • \D:非十進位數字 [^\d]
  • \s:空白字元 \p{IsWhite_Space}
  • \S:非空白字元 [^\s]
  • \w:文字 [\p{Alpha}\p{gc=Mn}\p{gc=Me}\p{gc=Mc}\p{Digit}\p{gc=Pc}\p-{IsJoin_Control}]
  • \W:非文字 [^\w]