トップ «前の日記(2010-07-02) 最新 次の日記(2010-07-17)» 編集

Route 477



2010-07-10

[ruby] Ruby 1.9と波ダッシュ問題に関するメモ

ややこしすぎるのでメモ

参考資料:

超参考書: 477414164X

  • UnicodeにはWAVE DASH(U+301C)という文字がある(波ダッシュ)
  • 波ダッシュは、「0時から6時」みたいなときに使われるアレ
  • UnicodeにはFULLWIDTH TILDE(U+FF5E)という文字もある(全角チルダ)
  • チルダは、ダイアクリティカルマーク*1の一種。スペイン語でnの上に付いたりするやつ
  • 見た目はだいたい同じ
  • フォントによっては、波打ち方が逆になってることもある
  • Shift_JISで使われる符号化文字集合は、JIS X 0201*2とJIS X 0208(第一第二水準漢字)
  • JIS X 0208の1区33点に、波ダッシュという文字がある
  • JIS X 0208に全角チルダはない
  • EUC-JPは、JIS X 0102・0208・0212(補助漢字)の文字を扱える
  • …のだけど、0212(補助漢字)はソフトウェアによっては実装されてなかったりするらしい*3
  • JIS X 0212には「ダイアクリティカルマークとしてのチルダ」がある。おいおい、JIS X 0102に半角チルダと被ってんじゃねーか
  • 一方WindowsはWindows_31J*4というShift_JISのスーパーセットを使った*5
  • さらに、WindowsにはeucJP-msとcp51932というEUC-JPの変種が2つあるらしい

おわかりいただけただろうか?(筆者はいただけてない)

irb-1.9で試行錯誤した結果を図にしてみる。

5289b464c58c8f653d2be08531ad2502.png

これを見ると、Ruby 1.9は基本的に波ダッシュ間で変換するが、Windows専用エンコーディングに関してはWindowsの流儀にならって全角チルダと変換するらしい。

(流儀っていうか歴史的経緯っぽいな。明確に間違いだとする説も)

矢印のない部分はUndefinedConversionError(例えば全角チルダをShift_JISに変換しようとするとか)。

ちなみにJIS X 0212のチルダがどうなるかというと、EUC-JPの"\x8f\xa2\xb7"は半角チルダ(ASCIIの)になる。ふーん。eucJP-msの場合は、波ダッシュと同様全角チルダになる。 CP51932は3バイトEUC非対応。

波ダッシュ問題

http://gihyo.jp/dev/serial/01/ruby/0004 には"WindowsのシフトJISをUnicodeへと変換する際には,必ずWindows-31Jを指定するようにしましょう"とある。なぜだろうか。

Mac OS XのターミナルではWAVE DASHもFULLWIDTH TILDEも表示できたが、WindowsのソフトではWAVE DASHが表示できなかったり、普通と逆に波打ってたりすることがあるらしい。

だからWindows上ではFULLWIDTH TILDEに変換した方が安全だよねーってことか。なるほどね。

(追記:iOSでも、http://favotter.net/status.php?id=18132572781 の波ダッシュがAeroReaderで文字化けしてた。WAVE DASHさん…)

マジコメ

どうしてもソースコードをSJISにしたいんです!というプロジェクトがあった場合にマジコメは「coding: shift_jis」とすべきか「coding: windows-31j」とすべきか。

文字列リテラル内に全角チルダがあって、それをUTF-8とかで出力する場合、shift_jisだとWAVE DASHが出る。windows-31jだとFULLWIDTH TILDEが出る。

MacやLinuxだとどっちも見れるみたいだから、Windowsのことを考えてwindows-31jにしとくのが無難か。

余談

ruby-1.9.1-p378 > dash.encode("euc-jpms").dump
Encoding::ConverterNotFoundError: code converter not found (UTF-8 to euc-jpms)

エンコーディング名がまちがってる時にこのエラーが出ると「UTF-8からEUC-JPmsには変換できないのかー」と勘違いしてしまうので、force_encodingのように「ArgumentError: unknown encoding name」って出してほしいな(あとでRedmine)

*1 関係ないけどこの用語かっこいいよね

*2 ASCIIの0x5C(バックスラッシュ)を「円記号」に、0x7E(半角チルダ)を「オーバーライン」にして、半角カタカナを加えた文字集合

*3 0102の半角カタカナ部分もそうらしい

*4 CP932, MS932とも呼ばれる

*5 空き部分に、ローマ数字とかのいわゆる機種依存文字が入ってる