シフトJISの『tr』によるひらがな→カタカナ変換は要注意(0x837Fに割り当てないよ〜)

知らなかった・・・


シフトJIS
ひらがな:[ぁ-ん]([0x829F-0x82F1])
カタカナ:[ァ-ン]([0x8340-0x8393])、[ヴ-ヶ](0x8394-0x8396)
文字コード数比較:

# -*- coding: Windows-31J -*-
## ひらがな文字数[ぁ-ん]
0x82F1 - 0x829F           # => 82
## カタカナ文字数[ァ-ン]
0x8393 - 0x8340           # => 83

カタカナの方が文字コード数が多い(>_<)
調べてみると0x837Fに割り当てがないんです!コレは気が付かないって。


気が付かないまま何をしていたかというと・・・
ひらがな→カタカナ変換:

# -*- coding: Windows-31J -*-
puts %w[にしとうきょう ひがしくるめ ひがしむらやま むさしむらやま].map{|s| s.tr('ぁ-ん','ァ-ン')}

結果:

ニシトウキユウ
ヒガシクリム
ヒガシ・ヨャマ
・サシ・ヨャマ

どこですか?w


シフトJISでのひらがな→カタカナ変換はこのようにしておきましょう!

# -*- coding: Windows-31J -*-
puts %w[にしとうきょう ひがしくるめ ひがしむらやま むさしむらやま].map{|s| s.tr('ぁ-みむめ-ん','ァ-ミムメ-ン')}

結果:

ニシトウキョウ
ヒガシクルメ
ヒガシムラヤマ
ムサシムラヤマ


これらの文字コード名が要注意?

# -*- coding: Windows-31J -*-
Encoding.find(Encoding.locale_charmap).names | Encoding.default_external.names | Encoding.find("Windows-31J").names |Encoding.find(:Shift_JIS).names
# => ["Windows-31J",
#     "CP932",
#     "csWindows31J",
#     "locale",
#     "external",
#     "Shift_JIS",
#     "SJIS"]
Windows-31J
CP932
csWindows31J
Shift_JIS
SJIS


追記:
Encoding.findはシンボルも引数指定できるのですが、『Windows-31J』のシンボルって『:Windows-31J』じゃダメなの?
エラーになっちゃうんですよね〜

# -*- coding: Windows-31J -*-
## これはOK
Encoding.find(:Shift_JIS).names
## これはNG
Encoding.find(:Windows-31J).names