PHP
正規表現
UTF-8
unicode
漢字

phpで漢字の正規表現を調べる(utf-8)

More than 3 years have passed since last update.

※この記事は異体字セレクタが考慮されていません。

phpでの漢字の正規表現を調べるをご参照ください。

Unicodeで「漢字」の正規表現

http://tama-san.com/?p=196

このページを参考にさせて頂きました。

結論から言うと

preg_match("/([\x{3005}\x{3007}\x{303b}\x{3400}-\x{9FFF}\x{F900}-\x{FAFF}\x{20000}-\x{2FFFF}])(.*|)/u", $hoge, $matches);

となります。

以下経緯

phpで文字が漢字かチェックするとき

[一-龠]という正規表現を使っていたのですが、

これだと繰り返し記号[々]が入ってないことがわかって、

他にも取りこぼしがないか調べてみました。


Unicodeの漢字の範囲はどこからどこまで?

unicodeの公式サイトでInput欄に\p{Han}を入れて検索すると

http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7BHan%7D&ucd=on

漢字の一覧が出てきます。

これを上から順に日本語の漢字の範囲を拾ってきます。


CJK Radicals Supplement

最初のセクションは

CJK Radicals Supplementという分類の


2E80 ;CJK RADICAL REPEAT 〜 2EF3 ;CJK RADICAL C-SIMPLIFIED TURTLE


⺀ (繰り返し)から始まって2E9Aを抜かして⻳まで。

一覧にすると

⺀⺁⺂⺃⺄⺅⺆⺇⺈⺉⺊⺋⺌⺍⺎⺏⺐⺑⺒⺓⺔⺕⺖⺗⺘⺙⺚⺛⺜⺝⺞⺟⺠⺡⺢⺣⺤⺥⺦⺧⺨⺩⺪⺫⺬⺭⺮⺯⺰⺱⺲⺳⺴⺵⺶⺷⺸⺹⺺⺻⺼⺽⺾⺿⻀⻁⻂⻃⻄⻅⻆⻇⻈⻉⻊⻋⻌⻍⻎⻏⻐⻑⻒⻓⻔⻕⻖⻗⻘⻙⻚⻛⻜⻝⻞⻟⻠⻡⻢⻣⻤⻥⻦⻧⻨⻩⻪⻫⻬⻭⻮⻯⻰⻱⻲⻳

となります。

見た感じ、書いたことも読んだこともないような文字が並んでいますね。

Unicodeの漢字はCJK統合漢字と言って

中国、日本、韓国で使われている漢字がごちゃまぜに入っているのです。

⻤(U+2EE4)とか⻨(U+2EE8)とかも入ってますが、

常用漢字の鬼(U+9B3C)麦(U+9EA6)とは別の字です。

なお、抜かしたU+2E9Aは欠番っぽいです。


Kangxi radicals

お次のセクションは

Kangxi radicalsという分類。


2F00 ;KANGXI RADICAL ONE 〜 2FD5 ;KANGXI RADICAL FLUTE


⼀⼁⼂⼃⼄⼅⼆⼇⼈⼉⼊⼋⼌⼍⼎⼏⼐⼑⼒⼓⼔⼕⼖⼗⼘⼙⼚⼛⼜⼝⼞⼟⼠⼡⼢⼣⼤⼥⼦⼧⼨⼩⼪⼫⼬⼭⼮⼯⼰⼱⼲⼳⼴⼵⼶⼷⼸⼹⼺⼻⼼⼽⼾⼿⽀⽁⽂⽃⽄⽅⽆⽇⽈⽉⽊⽋⽌⽍⽎⽏⽐⽑⽒⽓⽔⽕⽖⽗⽘⽙⽚⽛⽜⽝⽞⽟⽠⽡⽢⽣⽤⽥⽦⽧⽨⽩⽪⽫⽬⽭⽮⽯⽰⽱⽲⽳⽴⽵⽶⽷⽸⽹⽺⽻⽼⽽⽾⽿⾀⾁⾂⾃⾄⾅⾆⾇⾈⾉⾊⾋⾌⾍⾎⾏⾐⾑⾒⾓⾔⾕⾖⾗⾘⾙⾚⾛⾜⾝⾞⾟⾠⾡⾢⾣⾤⾥⾦⾧⾨⾩⾪⾫⾬⾭⾮⾯⾰⾱⾲⾳⾴⾵⾶⾷⾸⾹⾺⾻⾼⾽⾾⾿⿀⿁⿂⿃⿄⿅⿆⿇⿈⿉⿊⿋⿌⿍⿎⿏⿐⿑⿒⿓⿔⿕

部首の一覧らしいです。いらないですね。


CJK symbols and punctuation


3005 ;IDEOGRAPHIC ITERATION MARK

3007 ;IDEOGRAPHIC NUMBER ZERO


このセクションは々(反復記号)と〇(0)です。

〇はともかく々は使うので漢字の範囲に含めます。


HANGZHOU NUMERAL


3021 ;HANGZHOU NUMERAL ONE 〜 303A ;HANGZHOU NUMERAL THIRTY


蘇州号碼とかいう数字らしいです。含めません。


Other CJK punctuation


303B ;VERTICAL IDEOGRAPHIC ITERATION MARK


〻(反復記号)です。古文とかで出てくるので含めます。


CJK Unified Ideographs Extension A


3400..4DB5 ;CJK UNIFIED IDEOGRAPH-4DB5


CJK統合漢字拡張Aというもので、

主として地名や人名などに用いられる漢字が含まれているらしいです。含めます。


CJK Unified Ideographs


4E00..9FCC ;CJK UNIFIED IDEOGRAPH-9FCC


CJK統合漢字。日本語の漢字も含まれています。

冒頭で書いた[一-龠]がこの範囲ですね。一は4E00、龠は9FA0に当たります。

(ちなみに龠は「やく」で変換出来ます。中国の笛らしい。)

無視されてる9FA0から9FCCまでは

龡龢龣龤龥龦龧龨龩龪龫龬龭龮龯龰龱龲龳龴龵龶龷龸龹龺龻龼龽龾龿鿀鿁鿂鿃鿄鿅鿆鿇鿈鿉鿊鿋鿌

という漢字が並んでいます。

このセクションは4E00から9FFFまで領域が割り当てられており、

Unicodeがアップデートすると増えていく可能性があるので、9FFFまで指定します。


CJK Compatibility Ideographs


F900 ;CJK COMPATIBILITY IDEOGRAPH-F900 〜 FAD9 ;CJK COMPATIBILITY IDEOGRAPH-FAD9


CJK互換漢字。本来CJK統合漢字に統合されるはずなのに既存の文字コードとの互換性のためUnicodeに収録されてしまったらしいです。

日本で使うのは以下だけみたいだけど、実際どうなんだろう。


U+FA0E 〜 U+FA2D

IBM拡張漢字のうち、CJK統合漢字のブロックに収録されなかったもの。IRGを経由する漢字の通常の登録提案を経ずに、カナダからの提案としてISO/IEC 10646に収録されたため、「カナダ漢字」と呼ばれることがある

FA30 〜 FA6A

日本の文字コード規格JIS X 0213において人名許容・康煕別掲と呼ばれる漢字の一群と互換性を確保するために収録されたもの。

FA6B 〜 FA6D

日本のデータ放送規格ARIB STD-B24で使われる文字コードに収録されている独自の漢字(ARIB外字)のうち、既存の漢字に包摂されていると考えられるもの


CJK互換漢字はFAFFまで領域が割り当てられているので、Unicodeのバージョンアップを考えてFAFFまで指定します。


CJK Unified Ideographs Extension B


20000..2A6D6 ;CJK UNIFIED IDEOGRAPH-2A6D6


CJK統合漢字拡張B。JIS X 0213に一部対応しており、地名や人名などに用いられる漢字が含まれている。含めます。


CJK Unified Ideographs Extension C~F

これについては日本語の漢字であるという情報が見つからないのですが、

CJKのコードであるので一応含めておきます。

残りの拡張文字と、将来的に追加される漢字に対応するため2FFFまで指定します。


ここまで考慮したすべての正規表現

これで日本語の漢字にマッチさせる正規表現が出来ました。

preg_match("/([\x{3005}\x{3007}\x{303b}\x{3400}-\x{9FFF}\x{F900}-\x{FAFF}\x{20000}-\x{2FFFF}])(.*|)/u", $hoge, $matches);


Unicodeを文字に変換する

ところで、この正規表現に出てくるUnicodeの番号(コードポイント)ってどうやって文字に変換するのでしょうか。

一度コードポイントをバイナリに変換し、mb_convert_encodingでUTF-8にします。

$hoge = コードポイント;

mb_convert_encoding(pack( "N", $hoge ) , "UTF-8", "UCS-4");

他にも、こんな方法があるようです。

$hoge = コードポイント;

json_decode('"\u'.dechex($hoge).'"');

http://stackoverflow.com/questions/17539412/print-unicode-characters-php


参考資料

UTF-8の漢字の正規表現は[一-龠々]?

http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1229555292

Unicodeで「漢字」の正規表現

http://tama-san.com/?p=196

UTF-8 と UCS-4 の変換を php で行う場合の例

http://insnvlovn.blogspot.jp/2010/03/utf-8-ucs-4-php.html

CJK互換漢字

http://ja.wikipedia.org/wiki/CJK%E4%BA%92%E6%8F%9B%E6%BC%A2%E5%AD%97