コマンドラインで文字コードを自動判別する方法

シェルスクリプトコマンドラインで,テキストファイルの文字コードを自動判別する方法です

nkf を使う

head -n 1000 ファイル名 | nkf -g 

nkf -g ファイル名でも良いですが,nkfは遅いので,ファイルサイズが大きくなると処理に時間がかかります.アホみたいに待つ羽目になります.

実際に使うときは,ファイルの先頭1000行ぐらいをheadで切り取ってから nkf に渡すほうが良いでしょう

uchardet を使う

uchardet は比較的あたらしいツールです.高速に文字コードが判別できます.

www.freedesktop.org

インストール方法は debian/ubuntu 系なら

$ sudo apt-get install uchardet 

macportや homebrewでもパッケージが用意されています

使い方は

$ uchardet ファイル名

uchardet の出力は iconv 互換の文字列なので,そのままiconvコマンドに渡すことができます

例えばこのような形で

encoding=`uchardet 元ファイル`
iconv -f $fromcode -t utf-8 > 出力先ファイル名

文字コードを自動識別して,utf-8文字コードを変換する,という使い方になります

ベンチマーク

nkfと uchardet で処理時間はどの程度違うのでしょうか?

1.1GBのcsvファイル(2200万行)でベンチマークを取りました.測定条件は以下の通り

  • CPUは Intelの i7-11700 @ 2.50GHz
  • ディスクアクセスの影響が無視できるようにcsvファイルはRAMディスク上におく
  • time コマンドで処理時間(real)を測定


ベンチマーク結果

コマンド 処理時間
nkf -g 52.3秒
uchardet 0.47秒
head -n 1000 | nkf -g 0.013秒
head -n 1000 | uchardet 0.014秒

比較のために head -n 1000 の結果 nkf で判定するパターンにくわえて, uchardet で判定するパターンも測定しています

結果を見ると

  • データサイズが大きいときは head でファイルを切り出すのが効果的
    • nkfもuchardetもほぼ同じ処理時間
  • uchardet はやっぱり早い
    • 1.1GBのファイルが 一秒以下で判別できてます

このベンチはRAMディスクを使ってるのでdisk I/Oの負荷を無視した測定結果になっています.実際には disk I/Oがボトルネックになることもあるので uchardetを使うときも headを組みわせるなどしたほうがいいかもしれません.