以下、コマンドはすべてUTF-8環境下で実行するものとします。
UTF-8文字列をISO-8859-1(Latin-1)として解釈したケース
$ echo 典型的な漢字とEIJIとÉÏJÌの文字化けの種類と特徴 | iconv -f ISO-8859-1
å
¸åç
ãªæ¼¢åã¨EIJIã¨Ã ÃJÃã®æååãã®ç¨®é¡¨ç ¹å¾´
この実行コマンドのように、UTF-8文字列をiconv
で受け取るときに-f ISO-8859-1
と指定すると、入力(UTF-8)を無理矢理ISO-8859-1と解釈して取り込み、それをUTF-8にして出力します。
UTF-8ではASCII以外は全部MSB=1のバイトなので、æ とか å とか ã とかのISO-8859-1 right-hand sideに相当する文字ばかりに化けます。
端末に直接出力すると、80 から 9f の文字コードはC1制御文字として解釈されるために行や列の移動が起きて、一見不規則な位置に表示されることがあります。単なる文字列に変換するときには、それらは無視されたり表示不能文字の記号に変換されることが多いでしょう。
類似で、ISO-8859-1のスーパーセットのWindows-1252(CP1252)として解釈したケースも似た感じになりますが、C1制御文字がなく図形が割り当てられているので、記号類が出現しやすくなります。Windows-1252には 81 など未定義のコードがあるので、iconv
に-c
を付けています。
$ echo 典型的な漢字とEIJIとÉÏJÌの文字化けの種類と特徴 | iconv -c -f Windows-1252
典型的ãªæ¼¢å—ã¨EIJIã¨Ã‰ÃJÃŒã®æ–‡å—化ã‘ã®ç¨®é¡žã¨ç‰¹å¾´
いずれも、言語といえば欧米系ラテン文字のものしかないという認識の欧米圏発祥のシステムを国際化したが、UTF-8に対応しきれていないときに、よく表れる症状です。Safariがらみで見ることが多いのではないでしょうか。
UTF-8文字列をShift_JISとして解釈したケース
$ echo 典型的な漢字とEIJIとÉÏJÌの文字化けの種類と特徴 | iconv -c -f Shift_JIS
蜈ク蝙狗噪縺ェ貍「蟄励→EIJI縺ィテ嘉繍テ後譁ュ怜喧縺代遞ョ鬘槭→迚ケ蠕エ
UTF-8にはShift_JISに含まれないシーケンスがありうるので、iconv
に-c
を付けています。
日本語での使用頻度の少ないまたは使わないであろう漢字と半角カタカナ等が交互に並んだような特徴的な文字化けになります。
ひらがなとカタカナはUTF-8で e3 81 xx, e3 82 xx, e3 83 xx というバイト列になるので、一般的な漢字仮名まじり文が文字化けすると、Shift_JIS e3 81 = 縺, e3 82 = 繧, e3 83 = 繝 が頻出します。
(特にWindows用の)日本語対応システムを国際化したが、UTF-8に対応しきれていないときに、よく表れる症状です。BOMなしUTF-8のCSVをWindows版Excelで開いたときに誰もが見るやつです。また、以前はMac等で作成したZIPをWindowsで展開したときにファイル名がこのように化けました(今は対応済み)。そのほか、日本語といえばShift_JISでしょみたいな認識のシステムで発生します。
Shift_JIS文字列をIBM866として解釈したケース
$ echo 典型的な漢字とEIJIの文字化けの種類と特徴 | iconv -t Shift_JIS | iconv -f IBM866
УTМ^УIВ╚К┐ОЪВ╞EIJIВ╠Х╢ОЪЙ╗ВпВ╠ОэЧ▐В╞У┴Те
以下、日本語専用エンコーディングでは É や Ï は表記できないので入力から除外します。
IBM866(CP866)はロシアのDOSで利用されている(た?)キリル文字を含むコードページです。未定義のバイトはないので-c
は必要ありません。
見たとおり、キリル文字と罫線素片が交ざった特徴的な文字化けになります。
なぜIBM866として解釈するケースがあるのかと思われるかもしれません。実は、Linuxの標準的なディストリビューションに付属しているunzip 6.0改は、ファイル名がローカルエンコーディングのUTF-8で解釈できないときにOEM用(つまりWindows用)のアーカイブエンコーディングにフォールバックしますが、それがなぜか-O
で上書きしない限りCP866と定義されているのです。
というわけで、日本語WindowsでZIP圧縮ファイルを作成し(ファイル名はShift_JISでエンコードされる)、-O
をつけずにLinux上でunzipしてしまったとき、展開したディレクトリ名・ファイル名にこの文字化けが発生します。
ISO-2022-JP文字列でESCが脱落したケース
$ echo 典型的な漢字とEIJIの文字化けの種類と特徴 | iconv -t ISO-2022-JP | tr -d '\033'
$BE57?E*$J4A;z$H(BEIJI$B$NJ8;z2=$1$N<oN`$HFCD'(B
iconv -t ISO-2022-JP
でUTF-8をISO-2022-JPに変換したあと、tr
でESCのバイトを除去しています。
ISO-2022-JPではASCIIでない(全角の)文字列が ESC \$ B と ESC ( B で挟まれるシーケンスとなり、各文字はASCIIに相当するバイト2個で表現されます。このうちESCだけが脱落すると、\$Bと(Bで挟まれたランダムなASCIIの羅列となります。ひらがなは 24 xx、カタカナは 25 xx となるので、一般的な漢字仮名まじり文が文字化けすると、ASCII 24 = \$ や 25 = % が頻出します。
現在でも日本語のメール本文はISO-2022-JPでエンコードするというメーラーが多いですが、こうしたメールのソースを表示するときにESCのような制御文字を除去したり<1b>
のような別のシーケンスに変換してしまう処理系があり、そのような場合にこの文字列が発生します。メールが保存されたファイルをISO-2022-JPと指定せずにmore
やless
のようなテキストビューアで表示させても同様です。
次のような類似ケースがあり、これらはESCだけでなく \$B と (B も含めて除去した結果と同じです。
ISO-2022-JP文字列でエスケープシーケンスが脱落したケース
### ^[ は Ctrl+V ESC により入力
$ echo 典型的な漢字とEIJIの文字化けの種類と特徴 | iconv -t ISO-2022-JP | sed 's/^[[$(]B//g'
E57?E*$J4A;z$HEIJI$NJ8;z2=$1$N<oN`$HFCD'
EUC-JP文字列でMSBがクリアされたケース
$ echo 典型的な漢字とEIJIの文字化けの種類と特徴 | iconv -t EUC-JP | tr '\200-\377' '\000-\177'
E57?E*$J4A;z$HEIJI$NJ8;z2=$1$N<oN`$HFCD'
EUC-JP文字列をShift_JISとして解釈したケース
$ echo 典型的な漢字とEIJIの文字化けの種類と特徴 | iconv -t EUC-JP | iconv -c -f Shift_JIS
ナオキソナェ、ハエチサ、ネEIJI、ホハクサイス、ア、ホシホ爨ネニテトァ
EUC-JPの各バイトはASCIIにMSB=1をつけたものなので、ほとんどがShift_JIS半角カナの範囲内となり、半角カナが頻出します。
古いUNIX/Linuxで作成されたテキストファイルをWindowsで表示させようとすると、このような文字化けを多く見ることになります。
おわりに
これらに該当しない典型的なケースがみつかったら追記します。また、この文字化けがどういう経緯で起きたのかわからないというのがあれば、コメントでお知らせいただければ調べてみます。(判明するかはわかりませんが)
本記事は、以前、いわゆる増田に投稿したものに、加筆修正して掲載しています。元増田は削除しました。