在 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 方括號表示式的字元類,不過是以 \p
表示,例如測試小寫字母:
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)特性上,可以使用 IsHan
、script=Han
或 sc=Han
的方式來指定特性,例如測試漢字:
jshell> "林".matches("\\p{IsHan}");
$7 ==> true
對於 Unicode 區塊(block),也就是 Unicode 碼點範圍的指定,可以使用 InCJKUnifiedIdeographs
、block=CJKUnifiedIdeographs
或 blk=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]