日本社会で働くプログラマ、もとい非英語圏のプログラマにとって避けて通れないものが文字コード。とりわけ日本企業向けの受託開発を主とするSIerに勤めていると「年代物のメインフレームシステムが送ってくる、聞いたこともない文字コードのファイルをUnixベースのシステムに取り込む」「日本人大好きExcelで文字化けしないようにUTF-8のCSVをSJISに変える必要がある」などなど、文字コード変換を行う場面に出くわすことが多々あります。SIer勤めでなくとも、プログラマであれば文字コード周りのつらさはわかってもらえると思いますが、一方で文字コードほど非情報技術者にそのつらさがわかってもらえないものも珍しく、炎上とまではいわないものの、トラブルに発展することもないことではありません。
前置きはさておき、UnixやLinux環境において文字コード変換を行いたいときに利用するコマンドがiconv
。個人的にはよく利用するコマンドなので、その利用法やTipsなどを簡単にまとめておきたいと思います。
基本文法
たとえば「CP932のファイルcp932.txt
をUTF-8に変換し、その結果をutf8.txt
に出力したい」場合は次のように書きます。
iconv -f CP932 -t UTF-8 cp932.txt > utf8.txt
-f
オプションで変換元文字コードを、-t
オプションで変換後の文字コードをそれぞれ指定します。-f
が"FROM"、-t
が"TO"というわけです。なお__iconv
は変換結果を標準出力に出力します__。よって結果をファイルに書き出したい場合はリダイレクトしてやるか、あるいは以下のように-o
オプションを利用することになります。
iconv -f CP932 -t UTF-8 -o utf8.txt cp932.txt
2017-08-29 追記
書き忘れていましたが、iconv
は標準入力を取ることも可能です。
echo "stdin text" | iconv -f UTF-8 -t CP932
利用できる文字コードを調べたい
「手元の環境にインストールされているiconv
が変換できる文字コードを知りたい」という場合には-l
オプションを利用します。
root@mypc$ iconv -l
The following list contains all the coded character sets known. This does
not necessarily mean that all combinations of these names can be used for
the FROM and TO command line parameters. One coded character set can be
listed with several different names (aliases).
437, 500, 500V1, 850, 851, 852, 855, 856, 857, 860, 861, 862, 863, 864, 865,
866, 866NAV, 869, 874, 904, 1026, 1046, 1047, 8859_1, 8859_2, 8859_3, 8859_4,
8859_5, 8859_6, 8859_7, 8859_8, 8859_9, 10646-1:1993, 10646-1:1993/UCS4,
ANSI_X3.4-1968, ANSI_X3.4-1986, ANSI_X3.4, ANSI_X3.110-1983, ANSI_X3.110,
ARABIC, ARABIC7, ARMSCII-8, ASCII, ASMO-708, ASMO_449, BALTIC, BIG-5,
BIG-FIVE, BIG5-HKSCS, BIG5, BIG5HKSCS, BIGFIVE, BRF, BS_4730, CA, CN-BIG5,
CN-GB, CN, CP-AR, CP-GR, CP-HU, CP037, CP038, CP273, CP274, CP275, CP278,
(以降も文字コードの一覧が並ぶが、長すぎるので省略)
つまりiconv -l
は利用できる文字コードのリストを標準出力に出力します。あとはgrep
などを利用して、目当ての文字コードを探し-f
や-t
に指定するだけです。
変換エラーになるとき(変換エラーの文字を無視・置換したい)
さて機嫌よくiconv
による文字コード変換を行っていると、次のようなエラーに出くわすことがあります。
root@mypc$ iconv -f UTF-8 -t CP932 utf8.txt > cp932.txt
iconv: 位置 4 に不正な入力シーケンスがあります
これは文字コードの変換に失敗した、上の例でいえUTF-8にあってCP932にない文字をCP932に変換しようとしたということを意味します。
iconv
は通常、変換できない文字に出くわした場合「変換できたところまでを標準出力に出力したのち、エラーメッセージを標準エラー出力に出力して終わり」という形をとります。このような仕様は情報を損失を防ぐという点で「あり」なのかもしれませんが、多くの場合文字コード変換は情報損失を覚悟のうえで行っており、途中でやめてしまうよりは無視もしくは置換して変換を続行するほうが理にかなっていることも少なくありません。つまり変換できない文字の無視もしくは置換をiconv
で実現するにはどうすればよいでしょうか?
まず__無視したい場合は、-t
に指定する文字コードの後ろに//IGNORE
を付与するか、-c
オプションを利用するかのどちらかです。__
iconv -f UTF-8 -t CP932//IGNORE utf8.txt > cp932.txt
iconv -c -f UTF-8 -t CP932 utf8.txt > cp932.txt
次に__置換する場合、具体的には変換できない文字をそれらしい文字に置換する場合は-t
に指定した文字コードの後ろに//TRANSLIT
を付与します。__
iconv -f UTF-8 -t CP932//TRANSLIT utf8.txt > cp932.txt
たとえば「変換できない文字に出くわした場合は一律?
に置換したい」などなど、もっと細かく制御を行いたい場合はおとなしくPerlやRubyなどを利用しましょう(´・ω・`)