数値文字参照の数値の正体
絵文字の一覧を見てたんですよね。で、そのときに絵文字の記号の横に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進数にはできんのか。ちょっと残念。でもよくよく考えるとあんまり使う機会ないかも^^;
古い情報ではバイナリ埋め込まなきゃいけないとか SJIS 依存になってるだとかいろいろ制約があるけど、数値文字参照なら安心して普通のテキストとして操作できる。 ↩