nkfコマンドの罠?


nkfコマンドとは

Linuxで使える文字コード変換の王道?コマンドです。
オプションで、文字コード判別も利用できます。

今回はその文字コード変換で嵌ったのでめもめも

環境

こんな感じ

Linux VirtualBox 3.13.0-24-generic #46-Ubuntu SMP Thu Apr 10 19:11:08 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux


DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04 LTS"

# nkf -v
Network Kanji Filter Version 2.1.3 (2013-11-22) 
Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).
Copyright (C) 1996-2013, The nkf Project.

まずnkfの動きのおさらい

utf8のファイルとeucのファイルを準備します。

* 中身はこんな感じ
root@VirtualBox:/tmp# cat utf8-aiu.txt 
あいうえお
root@VirtualBox:/tmp# cat euc-aiu.txt 
あいうえお

* コードはちゃんとちがう
root@VirtualBox:/tmp# od -x utf8-aiu.txt 
0000000 81e3 e382 8481 81e3 e386 8881 81e3 0a8a
0000020
root@VirtualBox:/tmp# od -x euc-aiu.txt 
0000000 a2a4 a4a4 a6a4 a8a4 aaa4 000a
0000013

変換してみる(euc → utf8)

* ターミナルの設定がutf8なので普通にやるとバケバケ
root@VirtualBox:/tmp# cat euc-aiu.txt 
����������

* nkf -wでutf8にするとバケない(ちゃんと変換できてますねー)
root@VirtualBox:/tmp# nkf -w euc-aiu.txt 
あいうえお

ここまではOK!

文字コード判定してみる

root@VirtualBox:/tmp# nkf -g euc-aiu.txt 
EUC-JP

root@VirtualBox:/tmp# nkf -g utf8-aiu.txt 
UTF-8

よさげ。

次。

変な文字(unicode)でやってみる

root@VirtualBox:/tmp# cat unicode.txt 
«

root@VirtualBox:/tmp# od -x unicode.txt 
0000000 abc2 000a
0000003

こいつの、文字コードは?

root@VirtualBox:/tmp# nkf -g unicode.txt 
EUC-JP

!!! UTF-8じゃない。

で、いろいろ調べてみると。。

「«」(abc2)のバイトコードはeucでも存在しており(eucだと「束」)どうやらバイトコードかぶっていたようです。
で、さらにネットを漁ると、nkfの文字列判定の優先度があるっぽく、同一範囲だと
EUC-JP → SJIS → JIS → UTF-8
の順で判定されるみたいです。

でも、、、

root@VirtualBox:/tmp# nkf -w unicode.txt 
束
root@VirtualBox:/tmp# nkf -e unicode.txt 
«

これって逆じゃない?と思いました。。

変換後の状態は普通でしたが。。

root@VirtualBox:/tmp# nkf -w unicode.txt  > w-u.txt
root@VirtualBox:/tmp# nkf -e unicode.txt  > e-u.txt
root@VirtualBox:/tmp# od -x w-u.txt 
0000000 9de6 0a9f
0000004
root@VirtualBox:/tmp# od -x e-u.txt 
0000000 abc2 000a
0000003

ここだけよくわからず。。

念のため、以下(変な文字+utf8範囲の文字)も確認

root@VirtualBox:/tmp# cat unicode.txt 
«あ

root@VirtualBox:/tmp# nkf -g  unicode.txt 
UTF-8

root@VirtualBox:/tmp# nkf -w unicode.txt 
«あ

<ターミナルの設定をEUCにして>
root@VirtualBox:/tmp# nkf -e unicode.txt 
あ

これは想定どおり動いてくれました。

完。

おまけ

nkfの文字コード変換して上書きするオプション「--overwrite」 よく使います。