【シェルコマンド】nkfコマンドを使ってファイルの文字エンコーディングを判別し、iconvコマンドと連携させるやり方


2022/06/01

nkfコマンドNetwork Kanji Filterの頭文字をとった略語で、日本語などを含むテキストの文字エンコーディングを判別する際に非常にパワフルな機能を有しています。

nkfコマンドを標準でサポートしているLinuxOSも増えては来ているようですが、標準で使えないケースが多いです。

その意味ではLinux標準で幅広く文字エンコーディングを利用できる
iconvコマンドから、ファイルの文字エンコーディングを変換するほうがメジャーなやり方かと思います。

ただしiconvコマンドでは、ファイルの文字エンコーディングを推測して教えてくれる機能がないのでnkfコマンドを併用して、入力ファイルのエンコードの解析結果をパイプして、iconvでエンコード変換するような作業の簡略化を目指します。


ラズパイにnkfコマンドをインストールする

大抵のDebian系OSであれば、以下のコマンドでもパッケージインストールできるようになっています。

            
            $ sudo apt-get update && sudo apt-get upgrade -y
$ sudo apt-get -y install nkf
$ nkf --version
Network Kanji Filter Version 2.1.5 (2018-12-15)
Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).
Copyright (C) 1996-2018, The nkf Project.
        
Raspberry Pi OSでも幸いパッケージインストールできるので、有り難く使わせて頂くとします。


nkfコマンドでファイルの文字エンコードを判定する

nkfコマンドで文字エンコーディングを判別するオプションで、
-g / --guessというものを使います。

一見すると、--guessの簡略化が-gなので、どちらも同じ出力なのかと思いますが、現行のnkfコマンドでは表示が若干異なるようです。

            
            $ nkf -g shift_js.csv
Shift_JIS

$ nkf --guess shift_js.csv
Shift_JIS (CRLF)
        
以上、見てのように-gオプションでは文字コードだけが出力されていますが、--guessオプションだと文字コード 改行コードの2つが出力されるようなので注意が必要です。


nkfコマンドから文字エンコーディングを受け取り、iconvコマンドでファイル変換する

ではここから本題で、一例として、Shift-JISで保存した任意のファイル(ここではshift_jis.csv)を入力し、utf-8形式で標準出力させてみることを考えます。

まずはnkfコマンド無しでファイルの文字エンコーディングを変換する場合は、以下のようになります。

            
            $ iconv -f Shift-JIS shift_jis.csv
#👇文字エンコーディングが適合した場合、ファイルの中身が正しく表示される
...
        
もしくはcatなどでパイプの後段に付けて使うことも良くやります。

            
            $ cat shift_jis.csv | iconv -f Shift-JIS
#👇文字エンコーディングが適合した場合、ファイルの中身が正しく表示される
...
        

ここでのポイントとして、iconvコマンドで入力ファイルの文字エンコーディングを指定する場合、
-f/--from-codeを使います。

-fオプションに渡すエンコードタイプは、
iconv -lで対応できる種類が確認できます。

また、大文字小文字は区別されないので、例えば
SHIFT-JISなら、shift-jisでもShift-Jisでも同じエンコーディングと認識してくれます。

iconvは自動ではファイルのエンコーディングは判別してくれないので、ファイルの文字エンコーディングはあらかじめコマンド利用者が把握しておく必要があります。

例えば、ファイルの文字エンコーディングが不適合であった場合、以下のようにエラーになります。

            
            $ cat shift_jis.csv | iconv -f UTF-8
: 位置 0 に不正な入力シーケンスがあります
        
異なる文字エンコーディングのファイルが混在した形で大量に処理する必要がある場合、iconvコマンドだけを使って、一つ一つのファイルの文字エンコーディングを手で入力していくのは困難な作業です。

そのような場面に遭遇した場合、iconvコマンドへの文字エンコーディングの指定部分を、nkfコマンドで自動判別化すると、例えば以下のように非常に楽に標準出力が可能になります。

            
            $ ENC_TYPE=$(nkf -g shift_jis.csv)
$ cat shift_jis.csv | iconv -f $ENC_TYPE
#👇文字エンコーディングが適合し、ファイルの中身が正しく表示される
        
これだけで悩ましいファイルの文字エンコーディングの判別問題はおおかたクリアされると思います。

ワンライナーでやりたい場合にはxargsコマンドから、

            
            $ nkf -g shift_jis.csv | xargs -I{} iconv -f {} shift_jis.csv
        
とやる感じで利用できます。めでたしめでたし。

記事を書いた人

記事の担当:taconocat

ナンデモ系エンジニア

主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。