リニューアルしました & たまさん誕生日

これまですべて手書きだった「ものかの」ですが、ブログ(WordPress)に移行してリニューアルしました。まだ完全に移行しきれていませんけど、徐々に整備していきます。

以前のページへのリンクはリダイレクトするようにしたので、そのままで大丈夫だと思います。

それでは、どうぞ今後ともよろしく〜

そうそう、4/18 はたまさんの誕生日。
あれ? どうやってこの日が誕生日だと分かったんだっけ…?

Unicodeで「漢字」の正規表現

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

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

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

環境によってはUnicodeスクリプトの \p{Han} が使えます。対応するコードポイントの一覧はこちらで確認できます。
UnicodeSet で \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..4DBF と 4E00..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 を除外すると、人名地名がらみでいつか痛い目に会いそうです。やっぱり悩ましいですね…。

ちなみに [一-龠] はCJK統合漢字を不完全に範囲指定しています。さらに互換漢字ブロックがまるごと含まれていないので、Windows(CP932)のIBM拡張漢字のとりこぼしがあります。簡易な範囲指定だとしても(とくに DTP などでは)かなり危険。私は怖くてできません。

InDesign CS3 以降

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

「~K」にご不満な方はお試しあれ。(でもちょっと使いづらい…)

JavaScript

[々〇〻\u3400-\u9FFF\uF900-\uFAFF\u20000-\u2FFFF]

これダメです…。\u20000-\u2FFFF がヒットしません。解決方法を教えてください!

(?:[々〇〻\u3400-\u9FFF\uF900-\uFAFF]|[\uD840-\uD87F][\uDC00-\uDFFF])

えむけいさんが教えてくれました。感謝!

追記

[2011.3.1] 直井さんの InDesign CS3の漢字のメタ文字「~K」を検証する をつらつら見ていたところ、「括弧付き漢字」と「丸付き漢字」もあることに気づきました。あらー私はすっかり見落としていましたよ。で、これを加えると

[々〇〻\x{3220}-\x{3244}\x{3280}-\x{32B0}\x{3400}-\x{9FFF}\x{F900}-\x{FAFF}\x{20000}-\x{2FFFF}]

ますます使いづらいことに…。でも、この「括弧付き漢字」「丸付き漢字」は \p{Han} に含まれていないんですよねぇ、あらら。

Unicodeの特殊な文字 “結合文字列”

まともに Unicode のテキストを扱おうとすると、結合文字列はどうしても避けることのできない問題です。ここではあまり深く掘り下げずに、ユーザの眼を通してこれを見ていこうと思います。

まずはじめに、Unicodeには「特殊な文字」があることを知っておきましょう。

上図を見てください。これは Mac OS X のテキストエディットに入力した2つの「ポ」です。同じ文字が並んでいるだけのように見えます。でも実はこの2つ、文字データとしてはまったく違うものなんです。

左はいつも私たちが使っている1文字の「ポ」ですが、右は「ホ+半濁点」の2文字のデータで1文字になっています。これが Unicode の特殊な文字 “結合文字列” です。見た目が同じなので違いがまったく分かりません。

そこで違いを実感できるように「簡単なソフト」を作ってみました。
>> download(v0.4・Mac OS X 10.4 以降・2015/10/10更新)

左に「ポ」と手入力して NFD ボタンを押してください。右に Unicode の特殊な文字に変換されたポが表示されます。この特殊なポをマウスで触ってみましょう。「ホ」と「半濁点」の2つに分かれていますね。半濁点だけ選択してカットとペーストを繰り返すと面白いです。「2文字のデータで1文字になっている」とはどういうことなのか、実感してもらえたと思います。

さらに興味深い文字を見てみましょう。

[Get Glyph]ボタンの下に「01D6」とUnicodeのコードポイントを入力し、ボタンを押します。上にその文字が表示されます。小文字 u に音声記号が付いた文字ですね。[NFD]ボタンを押して変換してみます。なんと、2文字ではなく3文字で構成されていることが分かります。

次に[Get Glyph]ボタンの下に2組のコードポイント「00FC 0304」を入力してボタンを押します(半角スペースを間に入れます)。まったく同じ字形が表示されますね。

つまり、この文字は3通りの方法で表示できてしまうのです。

  • 01D6
  • 00FC 0304
  • 0075 0308 0304

この3通りの文字を「テキストエディット」にコピー&ペーストしてみましょう。

テキストエディットでは、どの文字も1文字として選択されます。さらに検索をしてみると、どの文字にもヒットします。3つが異なる文字データであることをまったく判別することができませんし、判別する方法もありません。もちろんこれはユーザへの配慮でそうなっているわけです。

さて、ここで専門用語を2つだけ覚えてください。

「結合」「結合文字列」

これまで見てきたように、Unicodeには「複数の文字で1つの字形を表示させる」という特殊な方法が用意されています。この方法を「結合 Combining」といいます。平易な言葉なのでつい読み流してしまいますが、Unicodeでは特殊な専門用語であることに注意してください。

そして、結合した複数文字のことを「結合文字列 Combining Character Sequence」といいます。見た目は1文字ですが、実際は複数文字なので「列」です。

Unicodeでは「ポ」などの文字を「音声記号がくっついた文字」と考えます。「音声記号の半濁点がくっついたホ」と見るわけですね。これを文字の形だけでなく、本当に文字データでも「音声記号がくっついた文字」にしたのが結合文字列です。

なお、これは覚えなくてもかまいませんが、結合文字列の中の音声記号(半濁点など)は「結合文字 Combining Character」といいます。これは結合文字列のためだけに用意された特殊な文字なので、単独で使われることはありませんし、単独で使ってもいけません。そして結合文字列「ホ+半濁点」の「ホ」の方は「基底文字 Base Character」と呼びます。

Mac OS X は結合文字列だらけ

さて、Unicodeの特殊な文字である「結合文字列」がどういうものかを見てきましたが、もしかすると、皆さんはこう疑問に思っているかもしれませんね。

「特殊な文字のことは分かった。でも、特殊なんだから、普通に作るテキストデータにそんな文字なんか無いのでは?」

実は、OS X には “結合文字列” がいたるところにあるのです。しかも、新しく簡単に作ることもできてしまいます。やってみましょう。

新規でフォルダを作ってください。「名称未設定フォルダ」という名前になりましたね。なんと、この名前の「ダ」が結合文字列なのです。「ダ」を「簡単なソフト」へコピー&ペーストしてみてください。2文字の結合文字列だと分かります。

OS X のフォルダやファイルなどの名称は、手入力をした場合でも、自動的に結合文字列にできる文字すべてが結合文字列に変換されます。ですから、名称をテキストにコピー&ペーストするだけで特殊な文字が混ざってしまうのです。

プログラマのための文字コード技術入門

文字符号化ブログに「自分のサイトに引っ越すことにしました」と書かれていたのでリンクをクリックしたところ、著書が掲載されていたので早速購入しました。

プログラマのための文字コード技術入門

文字コード関連の知識は、必要になった時点でそのつど行き当たりばったりに調べるのでかなりムラのある知識になってしまうのが普通です。そのムラをフラットにする技術解説書として、この本は非常に優れていると思いました。私自身の知識も相当すき間だらけでスカスカじゃんか! ということもしっかり確認できましたよ。

私が驚いたのは、紹介ページにあるこぼれ話でした。

また、Unicodeの正規化で置き換わってしまう互換漢字についても、編集者の手持ちのソフトウェアで問題のあるものがあったようです。確認のために「これでいいですか」といって送られてきたデータを見たら、ものの見事に互換漢字が統合漢字に置き換わってしまっていてびっくりしました。

Mac版InDesignでコピペしたのでしょうか…。怖い話です。(1

  1. Fill InDesign で解決したのなら嬉しいんですけどね〜 []