Unicode Property Escapesについての補説

 ECMAScript 2018よりRegExpで使えるようになったUnicodeプロパティーエスケープ (\p{...}, \P{...}) についての補説です。

メニュー

書式

 ECMAScript (JavaScript) の正規表現では、\p{...}, \P{...} ともに次のどちらかの書式を取ります。

 いずれの書式も{}内では大文字小文字が区別されます。

\p{NAME=VALUE}型

 \p{NAME=VALUE} という表現は、「Unicodeの全コードポイントのうち、NAMEという属性の値がVALUEであるものすべて」にマッチします。例えば \p{sc=Hira} という表記は、「Unicodeに存在するあらゆるひらがな」にマッチします。
 \P{...} は \p{...} とは逆に、「NAMEという属性の値がVALUEではないものすべて」にマッチします。\P{sc=Hira} という表記は「Unicodeに存在するひらがな以外のあらゆる文字」にマッチします。

 Unicode規格には様々な種類の属性が存在しますが、ECMAScriptではNAMEの部分に指定できる属性名を次の3つに限っています。

 前述の通り \p{...}, \P{...} とも ... の部分では大文字小文字が区別されますので、\p{GC=何々} や \P{script=何々} のように書くと認識されずエラーとなります。

General_Categoryの値一覧

 General_Categoryの値として指定できるのは次の文字列です。

General_Categoryの値一覧(括弧内は別名)
Cased_Letter (LC) Close_Punctuation (Pe) Connector_Punctuation (Pc) Control (Cc, cntrl)
Currency_Symbol (Sc) Dash_Punctuation (Pd) Decimal_Number (Nd, digit) Enclosing_Mark (Me)
Final_Punctuation (Pf) Format (Cf) Initial_Punctuation (Pi) Letter (L)
Letter_Number (Nl) Line_Separator (Zl) Lowercase_Letter (Ll) Mark (M, Combining_Mark)
Math_Symbol (Sm) Modifier_Letter (Lm) Modifier_Symbol (Sk) Nonspacing_Mark (Mn)
Number (N) Open_Punctuation (Ps) Other (C) Other_Letter (Lo)
Other_Number (No) Other_Punctuation (Po) Other_Symbol (So) Paragraph_Separator (Zp)
Private_Use (Co) Punctuation (P, punct) Separator (Z) Space_Separator (Zs)
Spacing_Mark (Mc) Surrogate (Cs) Symbol (S) Titlecase_Letter (Lt)
Unassigned (Cn) Uppercase_Letter (Lu)

Script, Script_Extensionsの値一覧

 ScriptおよびScript_Extensionsの値として指定できるのは次の文字列です(ECMAScript 2018現在)。

Script, Script_Extensionsの値一覧(括弧内は別名)
Adlam (Adlm) Ahom (Ahom) Anatolian_Hieroglyphs (Hluw) Arabic (Arab)
Armenian (Armn) Avestan (Avst) Balinese (Bali) Bamum (Bamu)
Bassa_Vah (Bass) Batak (Batk) Bengali (Beng) Bhaiksuki (Bhks)
Bopomofo (Bopo) Brahmi (Brah) Braille (Brai) Buginese (Bugi)
Buhid (Buhd) Canadian_Aboriginal (Cans) Carian (Cari) Caucasian_Albanian (Aghb)
Chakma (Cakm) Cham (Cham) Cherokee (Cher) Common (Zyyy)
Coptic (Copt, Qaac) Cuneiform (Xsux) Cypriot (Cprt) Cyrillic (Cyrl)
Deseret (Dsrt) Devanagari (Deva) Duployan (Dupl) Egyptian_Hieroglyphs (Egyp)
Elbasan (Elba) Ethiopic (Ethi) Georgian (Geor) Glagolitic (Glag)
Gothic (Goth) Grantha (Gran) Greek (Grek) Gujarati (Gujr)
Gurmukhi (Guru) Han (Hani) Hangul (Hang) Hanunoo (Hano)
Hatran (Hatr) Hebrew (Hebr) Hiragana (Hira) Imperial_Aramaic (Armi)
Inherited (Zinh, Qaai) Inscriptional_Pahlavi (Phli) Inscriptional_Parthian (Prti) Javanese (Java)
Kaithi (Kthi) Kannada (Knda) Katakana (Kana) Kayah_Li (Kali)
Kharoshthi (Khar) Khmer (Khmr) Khojki (Khoj) Khudawadi (Sind)
Lao (Laoo) Latin (Latn) Lepcha (Lepc) Limbu (Limb)
Linear_A (Lina) Linear_B (Linb) Lisu (Lisu) Lycian (Lyci)
Lydian (Lydi) Mahajani (Mahj) Malayalam (Mlym) Mandaic (Mand)
Manichaean (Mani) Marchen (Marc) Masaram_Gondi (Gonm) Meetei_Mayek (Mtei)
Mende_Kikakui (Mend) Meroitic_Cursive (Merc) Meroitic_Hieroglyphs (Mero) Miao (Plrd)
Modi (Modi) Mongolian (Mong) Mro (Mroo) Multani (Mult)
Myanmar (Mymr) Nabataean (Nbat) New_Tai_Lue (Talu) Newa (Newa)
Nko (Nkoo) Nushu (Nshu) Ogham (Ogam) Ol_Chiki (Olck)
Old_Hungarian (Hung) Old_Italic (Ital) Old_North_Arabian (Narb) Old_Permic (Perm)
Old_Persian (Xpeo) Old_South_Arabian (Sarb) Old_Turkic (Orkh) Oriya (Orya)
Osage (Osge) Osmanya (Osma) Pahawh_Hmong (Hmng) Palmyrene (Palm)
Pau_Cin_Hau (Pauc) Phags_Pa (Phag) Phoenician (Phnx) Psalter_Pahlavi (Phlp)
Rejang (Rjng) Runic (Runr) Samaritan (Samr) Saurashtra (Saur)
Sharada (Shrd) Shavian (Shaw) Siddham (Sidd) SignWriting (Sgnw)
Sinhala (Sinh) Sora_Sompeng (Sora) Soyombo (Soyo) Sundanese (Sund)
Syloti_Nagri (Sylo) Syriac (Syrc) Tagalog (Tglg) Tagbanwa (Tagb)
Tai_Le (Tale) Tai_Tham (Lana) Tai_Viet (Tavt) Takri (Takr)
Tamil (Taml) Tangut (Tang) Telugu (Telu) Thaana (Thaa)
Thai (Thai) Tibetan (Tibt) Tifinagh (Tfng) Tirhuta (Tirh)
Ugaritic (Ugar) Vai (Vaii) Warang_Citi (Wara) Yi (Yiii)
Zanabazar_Square (Zanb)
  • ECMAScript 2019以降は Dogra (Dogr), Gunjala_Gondi (Gong), Hanifi_Rohingya (Rohg), Makasar (Maka), Medefaidrin (Medf), Old_Sogdian (Sogo), Sogdian (Sogd) が追加される予定です(Unicode 11.0.0対応)。
  • ECMAScript 2020以降は Elymaic (Elym), Nandinagari (Nand), Nyiakeng_Puachue_Hmong (Hmnp), Wancho (Wcho) が追加される見込みです(Unicode 12.0.0対応)。

 HiraganaとKatakanaはあるのにKanjiがないと思われるかもしれませんが、Han (Hani) というのが漢字のことです(「漢字」の中国語読みをローマ字化したHanziに由来)。

ScriptとScript_Extensionsとの違い

 ScriptというのはUnicodeにおけるもっとも基本的な文字の分類単位です。日本語では文字体系、書記体系などと訳されることもありますが、今のところ定訳と呼べるようなものはまだないようです。
 例えばひらがなの「あ」(U+3042) は、Unicodeにおいては "Hiragana" scriptに属する文字のうちの一つであると見なされます。

 Unicodeでは文字を符号化する際、その符号化しようとしている文字がどのscriptに分類されるかをまず考えます。もし既存のどのscriptにも属するものではないと判断されれば、新しいscript名が登録され、その上で文字の符号化が行われます。いわばscriptとはディレクトリのようなもので、例えば先のひらがな「あ」であれば Unicode/Hiragana/あ のようにイメージしていただくと分かりやすいかもしれません。

 同名のファイルでもpathが異なれば別物であるように、見た目や発音が同じでもscriptが異なればUnicodeでは別の文字として扱われます。ラテン文字のA (U+0041)、ギリシア文字のΑ (U+0391)、キリル文字のА (U+0410) がUnicodeで区別されるのも、それぞれ別のscriptに属しているためです。ひらがなの「へ(U+3078)」とカタカナの「ヘ(U+30D8)」に別々の文字コードが割り振られているのも同じ理由です。

「異なるscriptに属する文字同士は、たとえ互いに似ていても別々の文字として扱われる」ということは、言い方を変えれば「1つの文字は複数のscriptに属することはできない」ということでもあります。従いましてUnicodeに存在するすべての文字は、1種類の \p{Script=何々} にしかマッチしません。

 しかし現実には、複数のscriptに跨って現れる文字というものも存在します。身近なところですと濁点(゛)や半濁点(゜)がそうです。これらは Hiragana script とも Katakana script ともどちらとも組み合わせて使われます。このような場合、どちらかのscriptに属させるわけにも行きませんので、これら2字は Common(汎用)という名前のscriptに分類されています。従って \p{sc=Hiragana} は、濁点にも半濁点にもマッチしません。

 このような文字が \p{何々=Hiragana} とも \p{何々=Katakana} ともどちらともマッチするようにしたのがScript_Extensionsです。例えば \p{scx=Hiragana} とすれば、先述の濁点・半濁点のみならず「、。・-」などにもマッチするようになります。さらにこれら「゛゜、。・-」は、\p{scx=Katakana} ともマッチします。

 Script_Extensionsにすると具体的にどの文字がどう変わるかについては、Scriptデータに対する差分の形で公開されています。

\p{LoneNameOrValue}型

 この書式が指定された場合、正規表現コンパイラはまず \p{General_Category=...} の "General_Category=" の部分が省略されたものと仮定し、General_Categoryとして指定できる値一覧の中に LoneNameOrValue と一致するものがあるかどうか調べます。
 その結果もしあれば、\p{General_Category=LoneNameOrValue} として処理を続けます。

 もしなかった場合、LoneNameOrValueの部分は binary property であると解釈され、この表現は「Unicodeの全コードポイントのうち、LoneNameOrValueで指定された属性値を持つものすべて」にマッチします。例えば \p{White_Space} という表記は、Unicodeに存在するあらゆる空白文字にマッチします。

Binary Property名一覧

 LoneNameOrValueの部分に指定できるのは次の文字列です(ECMAScript 2018現在)。

Binary Property名一覧(括弧内は別名)
ASCII ASCII_Hex_Digit (AHex)
Alphabetic (Alpha) Any
Assigned Bidi_Control (Bidi_C)
Bidi_Mirrored (Bidi_M) Case_Ignorable (CI)
Cased Changes_When_Casefolded (CWCF)
Changes_When_Casemapped (CWCM) Changes_When_Lowercased (CWL)
Changes_When_NFKC_Casefolded (CWKCF) Changes_When_Titlecased (CWT)
Changes_When_Uppercased (CWU) Dash
Default_Ignorable_Code_Point (DI) Deprecated (Dep)
Diacritic (Dia) Emoji
Emoji_Component Emoji_Modifier
Emoji_Modifier_Base Emoji_Presentation
Extender (Ext) Grapheme_Base (Gr_Base)
Grapheme_Extend (Gr_Ext) Hex_Digit (Hex)
IDS_Binary_Operator (IDSB) IDS_Trinary_Operator (IDST)
ID_Continue (IDC) ID_Start (IDS)
Ideographic (Ideo) Join_Control (Join_C)
Logical_Order_Exception (LOE) Lowercase (Lower)
Math Noncharacter_Code_Point (NChar)
Pattern_Syntax (Pat_Syn) Pattern_White_Space (Pat_WS)
Quotation_Mark (QMark) Radical
Regional_Indicator (RI) Sentence_Terminal (STerm)
Soft_Dotted (SD) Terminal_Punctuation (Term)
Unified_Ideograph (UIdeo) Uppercase (Upper)
Variation_Selector (VS) White_Space (space)
XID_Continue (XIDC) XID_Start (XIDS)

 ちなみに省略が認められているのは "General_Category=" だけで、"Script=" や "Script_Extensions=" の省略は認められていません。これらは=の右辺値が同じですので、\p{Katakana} のような表現だけでは \p{sc=Katakana} なのか \p{scx=Katakana} なのか区別が付かないためです。

参考資料