rm /blog

IT系技術職のおっさんがIT技術とかライブとか日常とか雑多に語るブログです。* 本ブログに書かれている内容は個人の意見・感想であり、特定の組織に属するものではありません。/All opinions are my own.*

【UNIX】iconvコマンド

UNIXには標準でiconvコマンドというのがついている。
コマンド一つでテキストファイルのエンコードを変換してくれる手軽で便利な機能である。
iconvコマンドの使い方を含めて、本項で備忘録のため記載する。



 

 
■基本的な使い方

基本的な使い方は以下の通りである。

iconv -f from-code -t to-code [-o output-file] input-file


-fは入力元ファイルのエンコード(from-code)
-tは変換先ファイルのエンコード(to-code)
-oは出力ファイルの名前(省略可能、この場合変換結果は標準出力される)


例えばとあるテキストファイル「aaa.txt」のエンコードを「UTF-8」から「MS932(SJIS)」に変換して「aaa2.txt」という名前で出力したい
という場合は、

iconv -f UTF-8 -t MS932 -o aaa2.txt aaa.txt


となる。

実行例:

$ cat aaa.txt
あいうえお
かきくけこ
さしすせそ
たちつてと
漢字

$ iconv -f UTF-8 -t MS932 -o aaa2.txt aaa.txt

$ file aaa2.txt
aaa2.txt: Non-ISO extended-ASCII text ←ファイルのエンコードが変換されていることがわかる

$ file aaa.txt
aaa.txt: UTF-8 Unicode text ←元ファイルの方はそのままUTF-8





■使用できるエンコード文字列(-lオプション)

ちなみに-fや-tに指定するエンコードの文字列は「iconv -l」で確認できる。

$ iconv -l
以下のリストには、知られているすべてのキャラクタコードが含まれています.
これは、これらの名前はコマンドラインパラメータのFROMとTOで使われる全ての
組合せを意味しているわけではありません. あるキャラクタセットは、
いくつかの異なる名前(エイリアス)と共にリストされます.

  …


一般的によく知られているエンコードは全部使えると思ってて良い。
UTF-8ISO-2022-JP、MS932(=CP932、MS932のエイリアス)、SJISEUC-JP、…



■不正文字の扱いとエラー回避(-cオプション)

UTF-8SJISのように、
fromの方(変換元)には文字があるがtoの方(変換先)には存在しない文字が元ファイルの方に含まれる場合は、「-c」オプションを付ける必要がある。
例えば「𩸽(U+29E3D、ほっけと読む。Unicodeの追加多言語面に存在)」を-cオプションなしでMS932に変換しようとすると

$ iconv -f UTF-8 -t MS932 -o aaa2.txt aaa.txt
iconv: 位置 5 で不正な入力シーケンスがありました

$ echo $?
1 ←戻り値1になる


↑こんなことをいわれてしまう。
同様の例としてMS932⇒ISO-2022-JPへの変換に際して、"①"等の機種依存文字を元ファイルに含む場合も失敗する。
-cオプションを付けるとこのエラーを回避できる。

$ iconv -f UTF-8 -t MS932 -o -c aaa2.txt aaa.txt ←-cオプションを付けて再実行

$ echo $?
0 ←戻り値0で正常終了



なお、ヘルプ上で「出力から不正な文字を抜かす」とあるように、
-cオプションを付けると上記のエラーが発生しなくなる代わりに
出力結果のファイルでこれに該当する文字は空白になって欠落してしまう。("?"にすらならない)
よって、外字等の複雑な文字を標準的に扱う仕組みだった場合、このやり方だと変換後の意味が通じなくなる可能性がある。
スクリプトに組み込む場合は、途中で処理が止まってしまうよりはエラーなく先に進んでもらう方がいいに決まってるのだが、
業務運用する面で考えると優しくない……この辺は自作対応が必要になるかも。



ちなみに、UTF-8の文字化け代表格といわれる「〜(U+301C)」や「∥(U+2225)」を含むファイルの変換においては、iconvはいい感じに変換をかけてくれている。
すなわちUTF-8:〜(U+301C)⇒SJIS:~(0x8160)というような具合である。