Unicodeで「漢字」の正規表現  2009.11.14 改訂

正規表現で漢字の範囲指定をする場合、シフトJISでは [亜-熙] になるのですけど、それでは Unicode ではどうするかが悩ましいところです。

[一-龠][\x{4E00}-\x{9FA0}])にしている例を見かけますが、実のところ、これは Unicode の膨大な漢字の中からシフトJISの [亜-熙] が含まれている範囲だけを切り出したものです。これを「Unicode のすべての漢字の範囲」と思っているのでしたら、完全に間違いなので [一-龠] にしてはいけません。

「Unicodeのすべての漢字」の正規表現 その1

環境によってはUnicodeスクリプトの \p{Han} が使えます。対応するコードポイントの一覧はこちらで確認できます。
UnicodeSet Demo で \p{Han} の対応コードポイント一覧を表示

「Unicodeのすべての漢字」の正規表現 その2

しかし、Unicodeスクリプトが使えない環境も普通にありますから、この場合はどうしましょうか…? 悩ましい〜

悩まなくていいのは \p{Han} に対応するコードポイントを網羅してしまう方法です。

[\x{2E80}-\x{2E99}\x{2E9B}-\x{2EF3}\x{2F00}-\x{2FD5}\x{3005}\x{3007}\x{3021}-\x{3029}\x{3038}-\x{303B}\x{3400}-\x{4DB5}\x{4E00}-\x{9FC3}\x{F900}-\x{FA2D}\x{FA30}-\x{FA6A}\x{FA70}-\x{FAD9}\x{20000}-\x{2A6D6}\x{2F800}-\x{2FA1D}]

Unicode のバージョンが上がって文字が追加されると、これでも足りなくなるおそれがあるので、それに対応できるよう未定義箇所を含めて指定してみます。ついでに隣接する箇所をなるべくまとめます。

[\x{2E80}-\x{2FDF}\x{3005}\x{3007}\x{3021}-\x{3029}\x{3038}-\x{303B}\x{3400}-\x{4DBF}\x{4E00}-\x{9FFF}\x{F900}-\x{FAFF}\x{20000}-\x{2FFFF}]

これが \p{Han} を網羅する最も簡潔な正規表現でしょうね。

しかし「こんなのヤダ〜!」と悲鳴をあげてしまいますねえ。そこで、日本語のテキスト処理で実用上問題ないところまでさらに少なくしてみます。

そこで「漢字の部首」「ハングル語の数字」を除外。

[\x{3005}\x{3007}\x{303B}\x{3400}-\x{4DBF}\x{4E00}-\x{9FFF}\x{F900}-\x{FAFF}\x{20000}-\x{2FFFF}]

もっと減らしたいですねえ。ここで考え方を変えて、分断されている範囲をちょっと強引にまとめてみます。3400..4DBF4E00..9FFF の間には「易経の大成卦」という普通は使わない文字が割り込んでいます。使わない文字にはヒットしないので、無いのと同じと考えて含めちゃいましょう。ついでに1文字しかない箇所はその文字を直接指定します。

[々〇〻\x{3400}-\x{9FFF}\x{F900}-\x{FAFF}\x{20000}-\x{2FFFF}]

内訳は以下のようになります。

3005 々(漢字の踊り字)
3007 〇(漢数字のゼロ)
303B 〻(漢字の踊り字)
3400..9FFF CJK統合漢字拡張A(+易経の大成卦)+CJK統合漢字
F900..FAFF CJK互換漢字
20000..2FFFF CJK統合漢字拡張B〜D+CJK互換漢字追加(+念のため)

私としては、これが限界だと思いますよ。もっと減らそうとして 20000..2FFFF を除外すると、人名地名がらみでいつか痛い目に会いそうです。やっぱり悩ましいですねえ…。

おまけ

InDesign CS3 以降の grep ではコレでOK。
[々〇〻\x{3400}-\x{9FFF}\x{F900}-\x{FAFF}\x{020000}-\x{02FFFF}]

これをテキストフレーム内にペーストして、それをコピーすれば、検索ウインドウの検索文字列にペーストできます。「~K」にご不満な方はお試しあれ。
(でもやっぱりちょっと使いづらい…)

追記

Javascript はコレ。
[々〇〻\u3400-\u9FFF\uF900-\uFAFF\u20000-\u2FFFF]

自分用のメモです…