2009-07-27

Unicode数値文字参照

数値文字参照の数値の正体

絵文字の一覧を見てたんですよね。で、そのときに絵文字の記号の横にUnicodeってのが書いてあるので、これ使えば基本的に対応機種は全部絵文字になるのかーこりゃ楽ちんだと思ったわけです1。でもハタと思いました。数値文字参照の数値ってどこから出てくるの?と。

09:34:40 >wtnabe< Unicode 数値文字参照の数字ってどこから出てきてるんだ
                  ろう
09:46:48 <gunyoki> @wtnabe っ http://unicode.org/charts/
09:48:50 >wtnabe< @gunyoki あーそうか、特定のUTFではなくUnicode、えーと
                  UCS? で表現されているわけですね。
09:50:13 >wtnabe< どうやって求めればいいんだろう。UCS
09:55:48 <gunyoki> @wtnabe さっきのチャートの文字の下に書いてある数値。
                   16進数なので、10進数に基数変換。
09:57:33 >wtnabe< @gunyoki すでにデータとして(Unicodeじゃないものが)あ
                  るんで、それを自動で変換したいってことなんです。この
                  辺の話なのかなと思っているところです。
                  http://blog.livedoor.jp/dankogai/archives/51048882.html
10:07:47 <gunyoki> @wtnabe もし日本語でJIS X 0212やJIS X 0213使ってない
                   なら、UnicodeのBMPに載るでしょうから、UTF-16にする手
                   段があれば、何でもいいんじゃないですかね。
10:11:59 >wtnabe< @gunyoki 分かったような分からない感じになっておりま
                  す…。精進します。
10:28:47 <gunyoki> @wtnabe たとえばシェルスクリプトだと、こんな感じ。
                   echo -n 'あいうえお' | nkf -w16L0 | od -tu2 -w2 |
                   awk '/[0-9]* [0-9]*/ { print "&#" $2 ";" }'
10:36:11 >wtnabe< @gunyoki ははー。なんとか pack/unpack でできるところ
                  まできました。ありがとうございます。

なるほど、おおもとのコード体系なわけね。Unicode ってだけ言われると周辺のいろんなこと想像しちゃってダメです。で、バイナリのデータは手に入ってるのでこれの変換をゴニョゴニョと試みます。基本的にはいつも一緒の irb に活躍してもらいます。

10:38:26 >wtnabe< Ruby の Fixnum.to_s だけで基数変換できるって初めて知っ
                  た。なにこれエロい。
10:59:46 >wtnabe< irb で Unicode 数値文字参照(hex表記)を得る '変態'.
                  toutf8.unpack( 'U*' ).map{ |e| "&#x#{e.to_s(16)};" }
                  でおk
10:59:58 >wtnabe< たぶん
11:01:47 <liar_l> @wtnabe 以前、似たようなことをしたかった時は、"あ".
                  encode('UTF-8').codepoints とかして逃げましたが。
11:03:03 >wtnabe< @liar_l 1.9使いの方ですか
11:10:47 <liar_l> @wtnabe 普段は1.8で生きてますが。これに関しては、1.9
                  のが楽だったので……。

最初はちょっと悩んだけど、分かってしまえばチョー楽じゃね?と思ったが 1.9 はさらに上手だった。なにその .codepoints って。

Ruby で基数変換

ついでに知った基数変換はこれ実にエロい。

i.to_s( n )

で n 進数に変換できる。ri をまんま貼付けると以下のようになる。

$ ri Fixnum#to_s
------------------------------------------------------------ Fixnum#to_s
     fix.to_s( base=10 ) -> aString
------------------------------------------------------------------------
     Returns a string containing the representation of _fix_ radix
     _base_ (between 2 and 36).

        12345.to_s       #=> "12345"
        12345.to_s(2)    #=> "11000000111001"
        12345.to_s(8)    #=> "30071"
        12345.to_s(10)   #=> "12345"
        12345.to_s(16)   #=> "3039"
        12345.to_s(36)   #=> "9ix"

あ、60進数にはできんのか。ちょっと残念。でもよくよく考えるとあんまり使う機会ないかも^^;

  1. 古い情報ではバイナリ埋め込まなきゃいけないとか SJIS 依存になってるだとかいろいろ制約があるけど、数値文字参照なら安心して普通のテキストとして操作できる。 

About

例によって個人のなんちゃらです