Unicodeエスケープまとめ: Java, Python, Ruby

| コメント(3) | トラックバック(0)

プログラムのソースファイルに文字を記すときに、キーボードから入力できなかったりフォントがなかったりといった理由で、Unicodeの符号位置を使って記したいことがあります。最近の言語では似た形式でそうしたUnicodeエスケープを記述できますが、微妙に違いがあります。ここではJavaとPython, Rubyを比べてみます。

JavaのUnicodeエスケープ

Javaではバックスラッシュ(\)とアルファベットのuに続けて4桁の16進数でUnicode符号位置を記します。

例えば、\u4e00 とすれば漢字の「一」を記したのと全く同じことになります。

JavaのUnicodeエスケープはコンパイルの初期段階で処理されるものなので、文字列リテラルの中で改行を意味する \n 等とは扱いが異なることに注意が必要です。このことは『プログラマのための文字コード技術入門』第7章に記しました。

'\u' の後に記す符号位置は厳密に4桁しか解釈されないので、BMP外の符号位置は直接記すことができません。サロゲートペアの上位下位をそれぞれ \u を使って記す必要があります。これは面倒な話で、いまだにこれしかないというのが信じられないのですが、Java 8版のJava Language Specificationをざっと見たところではほかの手段はなさそうです。(見落としてるかなぁ...)

PythonのUnicodeエスケープ

Pythonにも同様の記法があります。'u' の大文字小文字2種類があります。小文字の \u は16進4桁、大文字の \U は16進8桁で記します。例えばこうなります:

>>> print u"\u9bd6"
鯖
>>> print u"\U00029e3d"        ←BMP外の符号位置、魚の「ホッケ」の漢字
𩸽

(Python 2.7.5で動作確認)

ここで横着して頭のゼロ3つを省いてしまうとエラーになります。8桁というのは無駄な感じもしますが(ISO/IEC 10646の符号空間は以前は4バイト分ありましたが、今はUTF-16の範囲に限定してしまったので6桁で十分)、Javaと違ってサロゲートの値を使わずに済むのはいいですね。

RubyのUnicodeエスケープ

Ruby 1.9以降では、 \uXXXX という形と、波括弧を付けた \u{XXXX} という2種類が使えます。前者は4桁限定、後者は5桁・6桁でもOKです。

irb(main):013:0> print "\u9bd6"
鯖=> nil
irb(main):014:0> print "\u{29e3d}"
𩸽=> nil
irb(main):015:0> print "\u{9bd6 29e3d}"
鯖𩸽=> nil

(Ruby 2.0.0で確認。nil云々は無視して結構です)

波括弧を付けない記法で例えば \u29e3d のように5桁記してしまうと、"\u29e3" + "d" のように扱われてしまいますから、こうしたときは波括弧を用います。

最後の例のように、波括弧を使う記法ではスペースで区切って複数の符号位置を並べることができます。

トラックバック(0)

トラックバックURL: http://yanok.net/yanok/mt-tb.cgi/562

コメント(3)

JavaのUnicodeエスケープはおっしゃる通りUTF-16のコードユニット単位なので面倒です。どうもJavaはUCS-2で設計しちゃったから、いまさらコードポイントの扱いは面倒でも我慢してと言っているところがあるように感じます (個人の感想です)。互換上どうしようもなかったのだとは思いますが……

ところで、Javaの中でも正規表現 (java.util.regexパッケージ) はUnicode Technical Standard #18に準拠したためか (過去の互換性を気にする必要がなかったためか)、めずらしくコードポイント単位で処理が統一されています。そのためか、正規表現のパターンに関しては特別な構文が用意されています (Java7以降)。もちろん、正規表現パターンでしか使えません。

> \x{h...h} 16 進値 0xh...h を持つ文字 (後略)

この説明ではなんだかわかりませんが、h...h はコードポイントです。したがって

> たとえば、補助文字 U+2011F は、サロゲートペア \uD840\uDD1F の 2 つの連続する Unicode エスケープシーケンスの代わりに、\x{2011F} と指定できます。

という事になります。
補助文字という用語は正しいのでしょうが、なんだか嫌ですね (個人の感想です)。

正規表現の方はチェックしていませんでした。ご教示ありがとうございます。この記法が通常のUnicodeエスケープと同じに使えるといいのでしょうけど…。
「補助文字」は、BMPこそUnicodeという意識の名残なのでしょうかね。補助だったらサポートしなくていいやということになるとトラブルが温存されて困ってしまいます。

「補助文字」という用語は不適切だと思っているので、個人的には使わないようにして、「BMP以外の文字」のように言い換えるようにしています。

不適切だと思う理由は以下です。
・Supplementary という用語は「追加」のように訳すべきで、厳密には「補助」という意味では使われていない。
・Supplementary という用語は、面やブロックに対して使うのは理解できるが、コードポイントに使うのはおかしい (BMPにも文字は追加されている)。

コメントする

最近のブログ記事

National Geographic Your Shot で Daily Dozen に選ばれた話
ブログをさぼっている間に時間がずいぶん経…
情報処理学会から山下記念研究賞を頂いた話
ブログをさぼっている間に時間がずいぶん経…
Go と Rustの文字列
Go言語における文字列はUTF-8のバイ…
『[改訂新版] プログラマのための文字コード技術入門』のページ作成
発売されてから半年以上経ってようやくのこ…
『[改訂新版]プログラマのための文字コード技術入門』発売!
ばたばたしていて当サイトの更新も怠ってい…

広告