読者です 読者をやめる 読者になる 読者になる

JS.next

JavaScriptの最新実装情報を追うブログ

ユニコード文字プロパティについて

概要

正規表現でひらがなにマッチさせる場合によく「 /[ぁ-ん]/ 」とするが、これを「 \p 」エスケープ表現を使って、
「 /\p{Block=Hiragana}/u 」のように分かりやすく書けるようにするための新たな仕様がV8で実装された。
(※提案初期段階の仕様のため、この先廃止になったり仕様が大きく変わる可能性が大いにあります)


基本

文字の分類には様々なものがあり、その分類名nameと、その分類での値valueを使って、
「 /\p{name=value}/u 」のように記述する。

hiragana = /^\p{Script=Hiragana}+$/u           // スクリプト(言語文字種)分類:平仮名
console.log( hiragana.test( 'あいうえお' ) )   // true
console.log( hiragana.test( 'aiueo' ) )       // false 

// 分類名や値には大抵略称が1つ、または複数設定されており、そちらも使える
 
hira = /^\p{sc=Hira}+$/u                 // スクリプト分類:平仮名
console.log( hira.test( 'あいうえお' ) )   // true
console.log( hira.test( 'aiueo' ) )      // false 


ただし値が真偽値2通りの分類に関しては、「 =value 」を省略できる。
(小文字の「 \p 」の代わりに大文字の「 \P 」を使うことで否定的な意にできる)

dashT = /\p{Dash}/u              // ダッシュ分類:真 (Dash=Y)(Dash=YES)(Dash=T)(Dash=True)
dashF = /\P{Dash}/u              // ダッシュ分類:偽 (Dash=N)(Dash=NO)(Dash=F)(Dash=False)

console.log( dashT.test( '―' ) )  // true
console.log( dashF.test( '―' ) )  // false


また、『一般カテゴリー』分類に関しては「 name= 」(「 General_Category= 」)を省略して値のみを記述する。
更にその中で値が1文字の略称を持つものについては、その文字を「 X 」とすると全体で「 \pX 」の形で記述できる。

// 以下は全て同じ
punc = /\p{Punctuation}/u  // 一般カテゴリー分類:括弧 (General_Category=Punctuation)
punc = /\p{punct}/u 
punc = /\p{P}/u
punc = /\pP/u

console.log( punc.test( '[' ) )  // true


よく使いそうなパターン

数字

// 「 \pN 」が使えると言いたいところだが、これだと数字に纏わるあらゆる字が対象になってしまうので微妙である

num = /^\pN+$/u
console.log( num.test( '➊ⅱ¾㈤' ) )  // true
console.log( num.test( '六' ) )      // false  // ただし素の漢字は含まれない

// 「 \p{Nd} 」にすれば、各言語での代表的な数字くらいの範囲になる

dec = /\p{Nd}/u
console.log( dec.test( '➊ⅱ¾㈤' ) )  // false
console.log( dec.test( '6' ) )      // true   // 全角数字は含まれる
console.log( dec.test( '൬' ) )     // true   // マラヤーラム語で6
console.log( dec.test( '𝟞' ) )      // true   // こんなのも含まれる
console.log( dec.test( '六' ) )     // false  // ただし素の漢字は含まれない


平仮名・片仮名

hiraB = /\p{blk=Hiragana}/u  // (文字コード上での)ブロック分類:平仮名 (Block=Hiragana)
kataB = /\p{blk=Katakana}/u  // ブロック分類:片仮名

// スクリプト分類とブロック分類の仮名の分け方にはいくらか違いがある

hiraS = /\p{sc=Hiragana}/u
kataS = /\p{sc=Katakana}/u


// 濁点記号「 ゛ 」は、ブロック分類では平仮名に含まれるが、スクリプト分類では含まれない
//(スクリプト分類では他の記号などと一緒に「 Common 」に含まれる)

console.log( hiraB.test( '゛' ) )  // true
console.log( hiraS.test( '゛' ) )  // false


// 半角カナは、ブロック分類では片仮名に含まれないが、スクリプト分類では含まれる
//(ブロック分類では全角英数字などと一緒に「 Halfwidth_And_Fullwidth_Forms 」に含まれる)

console.log( kataB.test( 'ウ' ) )  // false
console.log( kataS.test( 'ウ' ) )  // true


// 長音記号「 ー 」は、ブロック分類では片仮名に含まれるが、スクリプト分類では含まれない
//(スクリプト分類では他の記号などと一緒に「 Common 」に含まれる)

console.log( kataB.test( 'ー' ) )  // true
console.log( kataS.test( 'ー' ) )  // false

// 片仮名で出来た組文字は、ブロック分類では片仮名に含まれないが、スクリプト分類では含まれる
//(ブロック分類では他の組文字などと一緒に「 CJK_Compatibility 」に含まれる)

console.log( kataB.test( '㌀' ) )  // false
console.log( kataS.test( '㌀' ) )  // true


漢字

hanS = /\p{sc=Han}/u               // スクリプト分類:汉字(漢字)
console.log( hanS.test( '汉' ) )   // true

// ブロック分類の方は互換漢字や拡張漢字が漏れるのであまりオススメしない

hanB = /\p{blk=CJK}/u              // ブロック分類:C(中国)J(日本)K(朝鮮)統合漢字 (blk=CJK_Unified_Ideographs)

console.log( hanS.test( '𠮷' ) )   // true
console.log( hanB.test( '𠮷' ) )   // false

// 逆にブロック分類の方はきめ細かい指定も可能

hanB2 = /\p{blk=CJK_Ext_B}/u       // ブロック分類:CJK統合漢字拡張B (blk=CJK_Unified_Ideographs_Extension_B)

console.log( hanB2.test( '𠮷' ) )  // true


記号ではない文字

alpha = /^\p{Alpha}+$/u  // 国語(で使われるような記号でない普通の文字)分類:真 (Alphabetic=YES)

console.log( alpha.test( 'abcイロハابت' ) )  // true


全角/半角

eaF  = /\p{ea=F}/u   // 東アジアにおける文字幅分類:全角 (East_Asian_Width=Fullwidth)
eaW  = /\p{ea=W}/u   // 広い(等幅フォントなら全角)     (ea=Wide)
eaA  = /\p{ea=A}/u   // 曖昧(等幅フォントなら全角かも) (ea=Ambiguous)
eaN  = /\p{ea=N}/u   // 中立(等幅フォントなら半角かも)  (ea=Neutral)
eaNa = /\p{ea=Na}/u  // 狭い(等幅フォントなら半角)     (ea=Narrow)
eaH  = /\p{ea=H}/u   // 半角                          (ea=Halfwidth)

zen1 = /^\p{ea=F}+$/u                    // 全角文字列
zen2 = /^[\p{ea=F}\p{ea=W}]+$/u          // 全角らしい文字列
zen3 = /^[\p{ea=F}\p{ea=W}\p{ea=A}]+$/u  // 全角っぽい文字列
console.log( zen3.test( 'あAα' ) )      // true


詳細仕様


実装されるバージョン

V8 5.0