UNIX/Linuxの部屋 コマンド:nkf

TOP UNIX/Linuxの部屋 UNIX/Linuxコマンド一覧 用語集 新版 由来/読み方辞書 環境変数マニュアル Cシェル変数 システム設定ファイル システムコール・ライブラリ ネットワークプログラミングの基礎知識 クラウドサービス徹底比較・徹底解説




コマンド nkf 文字コードや改行コードを変換する (パイプ) このエントリーをはてなブックマークに追加

最終更新


nkf コマンドは、UTF-8・EUC-JP・Shift_JIS・ISO-2022-JP などの文字コードを変換するツールである。また、改行コード・MIME・ROT13/47・URL エンコード・SGML 文字参照・カタカナ/ひらがな・いわゆる半角カナなども変換できる。

UNIX/Linux 系 OS ではおおむねパッケージが用意されているので、すぐに利用可能である。ちなみに Windows 版もある。

nkf コマンドは主に日本人が作成したものであり日本語に特化しているため、日本語関係ではまりがちな問題にも対応している。nkf コマンドは 1990年代前半から存在する歴史あるツールだが、2018年現在でも機能追加・メンテナンスがなされている。


nkf コマンドの基本的な使い方
ファイルの文字コードの変換は以下のとおり。
% nkf -w < file > file.utf8
→ file の文字コードを自動判別し、UTF-8 に変換し、file.utf8 に出力する。
% nkf -e < file > file.euc
→ file の文字コードを自動判別し、EUC-JP に変換し、file.euc に出力する。
% nkf -s < file > file.sjis
→ file の文字コードを自動判別し、Shift_JIS に変換し、file.sjis に出力する。
% nkf -j < file > file.jis
→ file の文字コードを自動判別し、ISO-2022-JP に変換し、file.jis に出力する。
nkf コマンドはファイルだけではなく、パイプ経由でも動作させることができる。
% cat file | nkf -w > file.utf8

-g オプションを使うと文字コードの自動判別を行う。
% nkf -g < file
Shift_JIS

改行コード変換には下記を行う。
% nkf -Lu < file > file.lf
→ 改行コードを LF に変換する (UNIX 式改行コードは LF)
% nkf -Lw < file > file.crlf
→ 改行コードを CR+LF に変換する (DOS/Windows 式改行コードは CR+LF)
% nkf -Lu < file > file.cr
→ 改行コードを CR に変換する (Mac OS 9 までの改行コードは CR。ただし Mac OS X からは LF)

ファイルを上書きするには --overwrite オプションを付ける。ワイルドカードを使って複数ファイルを一括変換することもできる。
% nkf --overwrite -e file
→ file を EUC-JP に変換
% nkf --overwrite -Lu *.txt
→ *.txt の改行コードを LF に変換

nkf コマンドのデフォルト挙動の注意点
nkf コマンドの注意点として、
  • デフォルトで MIME デコードする
  • デフォルトで半角カナを全角カナに置換する
ということを覚えておくとよい。
% echo "ア" | nkf

→ デフォルト挙動で半角カナを全角カナに置換してしまう
% echo "=?UTF-8?B?44GC44GE44GG?=" | nkf
あいう
→ デフォルト挙動で MIME をデコードしてしまう
このデフォルトでの変換を抑止するためには、nkf -x -m0 とする (-x で半角カナ変換抑止。-m0 で MIME デコード抑止)。

文字コードについての基礎知識
日本人がよく使う文字コードは、主に UTF-8/16/32、EUC-JP (UJIS とも言う)、SJIS (Shift_JIS)、ISO-2022-JP (JIS) の 4種類がある。

UNIX/Linux では EUC-JP が使われていたが、2000年代後半あたりから Unicode 環境が充実しはじめて、2018年現在では UTF-8 が主流ではないかと当ページ管理人は考える。

Windows や Mac では、日本においては Shift_JIS がよく使われている。ISO-2022-JP (JIS) は、7bit で収まるという特性から、メールやネットニュースで使用されていたが、2000年代後半から UTF-8 が使用されることが多くなった (Gmail などのメーラーが UTF-8 に対応したことと、ISO-2022-JP しか読めなかったガラケーがほぼ絶滅したため)。

UTF-8・UTF-16・UTF-32 は、Unicode 系の文字コードで、一般的には UTF-8 が主に使用されているものの、OS や言語の内部コードなどで UTF-16・UTF-32 が使われることもある。例えば Javascript の内部コードは UTF-16 と規定されている。UTF-16 は、ビッグエンディアンとリトルエンディアン、BOM あり・なし という話は、いつか書く。

文字コードの自動判別・推測について
nkf コマンドでは -g オプションで自動判別結果を教えてくれる。
% nkf -g < file
Shift_JIS

上記のように文字コードの自動判別・推測はおおむね可能ではあるものの、複数の文字コードとして解釈できるバイト列が存在するため、精度は 100% ではない。特に対象ファイルが数バイト程度である場合、誤判断につながる可能性が高くなる。

例として、下記のように EUC-JP の半角カナ "ア" と、Shift_JIS の "竺" は、全く同じバイト表現になる。
% echo -n ア | nkf -Wex | od -tcx1
0000000 8e b1
→ 入力を UTF-8 (-W)・出力を EUC-JP (-e)・半角カナ変換 OFF (-x) としたもの
% echo -n 竺 | nkf -Ws | od -tcx1
0000000 8e b1
→ 入力を UTF-8 (-W)・出力を Shift_JIS (-s) としたもの
これを nkf -g は、両方とも Shift_JIS とみなしてしまう。
%echo -n ア | nkf -Wex | nkf -g
Shift_JIS
% echo -n 竺 | nkf -Ws | nkf -g
Shift_JIS
しかし、半角カナがあっても、それ以外に漢字・平仮名・全角カナなどがあると EUC-JP と正しく判断できる。よって、あまりに短い文字列を自動判別するのはおすすめしない。
%echo -n ほげほげア | nkf -Wex | nkf -g
EUC-JP

また、まれにファイル内に異なる文字コードが含まれている場合もあるため、判別に失敗する場合もある。例えば Web アプリケーションで、クライアント (ブラウザ) から受け取った入力を同一ファイルに保存していたりすると、たまに変な文字コードで送ってくるクライアントが存在するので、1ファイル内でエンコーディングが混在してしまう。

以下は、複数の文字コードを混在させて nkf -g が何と判別するかを試したものであるが、UTF-8・Shift_JIS などは "BINARY" と正しく (?) 判別するが、EUC-JP・Shift_JIS 混在の場合は、誤って Shift_JIS と判別されてしまった。
% ((echo ほげほげ | nkf -w); (echo ほげほげ | nkf -s)) | nkf -g
BINARY
→ UTF-8 と Shift_JIS 混在
% ((echo ほげほげ | nkf -j); (echo ほげほげ | nkf -s)) | nkf -g
BINARY
→ ISO-2022-JP と Shift_JIS 混在
% ((echo ほげほげ | nkf -e); (echo ほげほげ | nkf -s)) | nkf -g
Shift_JIS
→ EUC-JP と Shift_JIS 混在

nkf コマンドのオプション - 文字コード関連
出力の文字コード (エンコーディング) 指定。
-w UTF-8 コードに変換
-w16 UTF-16 コードに変換 (BOM あり・ビッグエンディアン)
-w16B UTF-16 コードに変換 (BOM あり・ビッグエンディアン)
-w16L UTF-16 コードに変換 (BOM あり・リトルエンディアン)
-w160 UTF-16 コードに変換 (BOM なし・ビッグエンディアン)
-w16B0 UTF-16 コードに変換 (BOM なし・ビッグエンディアン)
-w16L0 UTF-16 コードに変換 (BOM なし・リトルエンディアン)
-w32 UTF-32 コードに変換 (BOM あり・ビッグエンディアン)
-w32B UTF-32 コードに変換 (BOM あり・ビッグエンディアン)
-w32L UTF-32 コードに変換 (BOM あり・リトルエンディアン)
-w320 UTF-32 コードに変換 (BOM なし・ビッグエンディアン)
-w32B0 UTF-32 コードに変換 (BOM なし・ビッグエンディアン)
-w32L0 UTF-32 コードに変換 (BOM なし・リトルエンディアン)
-e EUC-JP (EUC-JP) コードに変換
-s SJIS (Shift_JIS) コードに変換
-j JIS (ISO-2022-JP) コードに変換
% nkf -e sample > sample.euc
⇒ ファイル sample の文字コードを EUC に変換して sample.euc に出力する
入力の文字コードは、デフォルトでは自動判別であるが、明示的に指定することもできる。
-W 入力を UTF-8 コードとみなす
-W16 UTF-16 コードとみなす (BOM あり・ビッグエンディアン)
-W16B UTF-16 コードとみなす (BOM あり・ビッグエンディアン)
-W16L UTF-16 コードとみなす (BOM あり・リトルエンディアン)
-W160 UTF-16 コードとみなす (BOM なし・ビッグエンディアン)
-W16B0 UTF-16 コードとみなす (BOM なし・ビッグエンディアン)
-W16L0 UTF-16 コードとみなす (BOM なし・リトルエンディアン)
-W32 UTF-32 コードとみなす (BOM あり・ビッグエンディアン)
-W32B UTF-32 コードとみなす (BOM あり・ビッグエンディアン)
-W32L UTF-32 コードとみなす (BOM あり・リトルエンディアン)
-W320 UTF-32 コードとみなす (BOM なし・ビッグエンディアン)
-W32B0 UTF-32 コードとみなす (BOM なし・ビッグエンディアン)
-W32L0 UTF-32 コードとみなす (BOM なし・リトルエンディアン)
-E 入力を EUC-JP (EUC-JP) コードとみなす
-S 入力を SJIS (Shift_JIS) コードとみなす
-J 入力を JIS (ISO-2022-JP) コードとみなす

nkf コマンドのオプション - エンコード・デコード関連
-m MIME をデコードする (デフォルト)
メールの Subjectなどには生の日本語ではなく、MIME を書く。例えば
=?iso-2022-jp?B?GyRCJE8kOCRhJF4kNyRGGyhK?=
を MIME デコードすると
% echo '=?iso-2022-jp?B?GyRCJE8kOCRhJF4kNyRGGyhK?=' | nkf -m
はじめまして
となる。nkf のバージョンが古い場合、iso-2022-jp の部分が小文字だと変換できないことがある。この場合は「iso-2022-jp」を「ISO-2022-JP」に変えればよい。
nkf コマンドはデフォルトで MIME デコードを行うようになっているため、MIME デコードを抑止したい場合は -m0 オプションを使う。
-m0 MIME デコードを抑止する。
-M MIME エンコードする。
% echo あいう | nkf -M
=?UTF-8?B?44GC44GE44GG?=
% echo あいう | nkf -M -j
=?ISO-2022-JP?B?GyRCJCIkJCQmGyhC?=
→ -j オプションで ISO-2022-JP に変換した上で MIME エンコード
% echo ああああああああああああああああああいう | nkf -M -j
=?ISO-2022-JP?B?GyRCJCIkIiQiJCIkIiQiJCIkIiQiJCIkIiQiJCIkIiQiJCIkIiQiGyhC?=
=?ISO-2022-JP?B?GyRCJCQkJhsoQg==?=
→ 長い文字列は分割されて複数行になる (MIME ヘッダエンコーディング 78 バイト制限)
-MB Base64 形式にエンコードする
% echo -n 'abcほげ' | nkf -MB
YWJj44G744GS
-MQ Quoted-printable 形式にエンコードする
% echo -n 'abcほげ' | nkf -MQ
abc=E3=81=BB=E3=81=92
-x 半角カナを維持する
nkf はデフォルトではいわゆる半角カナを全角カナに置換してしまう。置換を抑止するためには -x オプションを指定する。
-Z[0-3] 特定の全角文字を半角に置換する
-Z0 は、いわゆる全角英数字記号を半角に置換する。
% echo 'ABC012*+?' | nkf -Z0
ABC012*+?
-Z1 は、全角スペースを半角スペース 1つに置換する。
% echo "[ ]" | nkf -Z1
[ ]
-Z2 は、全角スペースを半角スペース 2つに置換する。
% echo "[ ]" | nkf -Z2
[ ]
-Z3 は、全角の「<」「>」「&」「”」を、それぞれ実体参照に変換する。
% echo '<>&”' | nkf -Z3
&lt;&gt;&amp;&quot;
--url-input URL エンコーディングをデコードする
% echo "%21%22%23" | nkf --url-input
!"#

nkf コマンドのオプション - その他
-r ROT13/47 変換を行う。
ROT13 は、アルファベットを 13個ずらす変換で、例えば a は n に、b は o になる。
% echo abcABC | nkf -r
nopNOP
アルファベットは 26個であるため、もう一度 ROT13 を行うと下記のように元に戻るのがミソである。
% echo abcABC | nkf -r | nkf -r
abcABC
ROT47 は、英字だけではなく、数字・記号などもローテートするもので、入力が ASCII なら ROT13、そうでないなら ROT47 となるはずなのだが、当ページ管理人の環境ではなぜかどうやっても数字がローテートされなかった。
-f 日本語を含む文章の fold。
% nkf -f 30 < file
⇒ file の出力を1行あたり30文字に整形する。
fold コマンドと違い、日本語を含む文章でも正しく処理することができる。
-g または --guess
nkf コマンドは入力データのエンコーディングを自動判別 (推測) するが、その結果を出力する。-g ではエンコーディング名のみ、--guess はそれに加えて改行コードも表示する。
% nkf -g < file
UTF-8
→ --guess=2 や -g1 でも同じ。
% nkf --guess < file
UTF-8 (LF)
→ --guess=2 や -g2 でも同じ。
複数ファイルを渡すと、それぞれのエンコーディングを表示する。
% nkf -g *
file1: UTF-8
file2: BINARY
file3: EUC-JP

nkf コマンドには、以前は上書き機能が存在しなかったので、そういうときは qkc コマンドを使うと便利、と言われていたが、qkc コマンドは開発が止まっており、Unicode 対応もなされていないため、現在は使う必要はないだろう。
ファイル内容ではなくファイル名の文字コードを変更する場合は、convmv コマンドを使うとよい。

読み方 nkf (UNIXコマンド) [えぬ・けー・えふ] このエントリーをはてなブックマークに追加

ネットワーク用漢字コード変換フィルタの略。