京橋のバイオインフォマティシャンの日常

データ分析、コマンドライン、プログラミングについての技術資料・自己アップデート・悩み事などをまとめています。現在、DL勉強中。

文字コード変換コマンド 〜シングルバイト文字、マルチバイト文字、JIS、Shift_JIS、UTF-8、BOM付きUTF-8、Unicodeエスケープ文字、URLエンコードなどの諸問題について〜

シングルバイト文字・マルチバイト文字

「シングルバイト文字」は、1バイト(7ビット、または8ビット)のデータ量で表現できる文字である。文字コードとしては、ASCIIコードなどが該当する。

一方、ダブルバイト文字は、1文字を2バイト以上(16ビット以上)のデータ量で表現できる文字である。JISコード、Shift JISコードなどがそれに該当する。

以下、簡単な表にまとめてみた。

文字の種類 説明 文字コードの例
シングルバイト文字*1 1バイト(7ビットまたは8ビット)のデータ量で表現できる文字 主にアルファベットや数字
ASCIIコード、ISO/IEC 8859 など
ダブルバイト文字 *2 1文字を2バイト以上のデータ量で表現できる文字 JIS X 0208、JISコード、Shift JISコード、EUC-JP、など

UTF・BOM

UTF-8 *3やUTF-16 *4は、Unicode / UCS *5で定義された文字集合で表現できる文字コードである。

Unicodeには、「BOM無し」と「BOM付き」の2種類のファイルが存在する。 BOMは、「バイトオーダーマーク(Byte Order Mark)」の略で、 Unicodeで符号化したテキストの先頭に付与される数バイトのデータのことを指す。 具体的には、バイナリの先頭に付く、<0xEF 0xBB 0xBF> が BOM である。

実際、UTF-8のファイルにはBOMは必要ないものであるが、 「Excel」「メモ帳」など Microsoft のアプリ、Macのアプリでは、 「BOM」を付けないと、日本語文字がうまく読めず、文字化けを起こすことがある。

Unicodeエスケープ文字・パーセントエンコード文字

「\uXXXX」といったUnicodeエスケープ文字、「%XX」といったURLエンコード(パーセントエンコード)文字というのがある。

Unicodeエスケープ形式の文字では、「\u」に文字の符号位置を表す16進数の値を付加することで、1文字を 「\uXXXX」 のような16進数4桁のコード形式にて表す。

また、パーセント・エンコード形式の文字では、「%」に16進数の値を付加することで、1文字を「%XX」のような16進数2桁のコード形式にて表す。

日本語などの文字列は、URLとしてそのまま扱うことができないため、エンコード形式の文字を使用する。URLとして使う際に、「%」付きの半角英数字・記号に変換することから、「URLエンコード」と呼ばれる。逆に、元の文字列に戻すことを「URLデコード」という。

今回の内容

主に、nkfコマンドを用いた、文字コードの変換例をまとめてみた。

nkfコマンドの基本的な使い方

nkfは、ものすごく古い漢字コード変換プログラムである*6

まず、Homebrewで、nkfコマンドをインストールする。

ターミナルを起動して、以下を実行する。

#nkf コマンドのインストール
brew 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.

#【nkfコマンドの主なオプション】
#-u: 出力時にバッファリングを行わない
#-j: JISコードに変換する
#-e: EUCコードに変換する
#-s: Shift JISコードに変換する
#-w: UTF8コードに変換する
#-r: ROT13/47の変換する
#-T: テキスト・モードで出力する
#file: 変換元のファイルを指定する
#-g: 文字コード自動判別の結果を表示
#–overwrite: 引数のファイルに直接上書き

nkfコマンドでの文字コードの変換例

テスト・ファイルをダウンロードする。

wget https://raw.githubusercontent.com/kumeS/Blog/master/nkf_test/test.txt 

ファイルの文字コードを表示

nkf -g test.txt
#UTF-8

Shift JISコードに変換する。

nkf -s test.txt > test01.txt

#ファイルの文字コードを表示
nkf -g test01.txt
#Shift_JIS

#上書きの場合
#nkf -s --overwrite test.txt

UTF8コードに変換する。

nkf -w test01.txt > test02.txt

#ファイルの文字コードを表示
nkf -g test02.txt
#UTF-8

#上書きの場合
#nkf -w --overwrite test01.txt

UTF-8からUTF-8(BOM付)への変換

#nkfで、BOM付きに変換
nkf --oc=UTF-8-BOM test.txt > test_BOM.txt

#上書きの場合
#nkf --overwrite --oc=UTF-8-BOM test.txt 

#OR
#テキストの先頭にBOM文字列を、catで追記する
#cat <(printf "\xEF\xBB\xBF") BOM無しファイル.txt > BOM付きファイル.txt
#ダブルクォーテーションは半角で、、

cat <(printf "\xEF\xBB\xBF") test02.txt > test02_BOM.txt

見た目では分からないが、エクセルとかで開いてみると違いがわかる。

Unicodeエスケープシーケンス形式を日本語文字に変換する

別のテスト・ファイルをダウンロードする。

wget https://raw.githubusercontent.com/kumeS/Blog/master/nkf_test/nkf_test.txt

#例題
cat nkf_test.txt

#\u30D9\u30EB\u30AE\u30FC
#\u5E78\u798F
#\u30B8\u30E7\u30FC\u30B8\u30FB\u30EF\u30B7\u30F3\u30C8\u30F3
#\u30B8\u30E3\u30C3\u30AF\u30FB\u30D0\u30A6\u30A2\u30FC
#\u30A6\u30A3\u30AD\u30C7\u30FC\u30BF
#\u5357\u6975\u5927\u9678
#\u30B3\u30F3\u30D4\u30E5\u30FC\u30BF

それでは、Unicodeエスケープシーケンス形式の文字を日本語文字に変換してみる。

# エスケープ文字を日本語に変換する(デコード)
cat nkf_test.txt | sed 's/\\\u\(....\)/\&#x\1;/g' | nkf --numchar-input -w > nkf_test2.txt

#変換結果を表示
cat nkf_test2.txt
#ベルギー
#幸福
#ジョージ・ワシントン
#ジャック・バウアー
#ウィキデータ
#南極大陸
#コンピュータ

#エンコードについては、改行の入れ方を少し検討中
#cat nkf_test2.txt | iconv -t UCS-2 | xxd -p | fold -w4 | xargs -n1 printf '\\u%s' > nkf_test2_encode.txt
#cat nkf_test2_encode.txt
#\u30d9\u30eb\u30ae\u30fc\u000a\u5e78\u798f\u000a\u30b8\u30e7\u30fc\u30b8\u30fb\u30ef\u30b7\u30f3\u30c8\u30f3\u000a\u30b8\u30e3\u30c3\u30af\u30fb\u30d0\u30a6\u30a2\u30fc\u000a\u30a6\u30a3\u30ad\u30c7\u30fc\u30bf\u000a\u5357\u6975\u5927\u9678\u000a\u30b3\u30f3\u30d4\u30e5\u30fc\u30bf\u000a

パーセント・エンコードを日本語文字に変換する

パーセント・エンコード文字を日本語文字に変換してみる。

#パーセント・エンコード: 日本語 => パーセント文字
cat nkf_test2.txt | nkf -WwMQ | tr = % > nkf_test3.txt

#変換結果を表示
cat nkf_test3.txt
#%E3%83%99%E3%83%AB%E3%82%AE%E3%83%BC
#%E5%B9%B8%E7%A6%8F
#%E3%82%B8%E3%83%A7%E3%83%BC%E3%82%B8%E3%83%BB%E3%83%AF%E3%82%B7%E3%83%B3%
#%E3%83%88%E3%83%B3
#%E3%82%B8%E3%83%A3%E3%83%83%E3%82%AF%E3%83%BB%E3%83%90%E3%82%A6%E3%82%A2%
#%E3%83%BC
#%E3%82%A6%E3%82%A3%E3%82%AD%E3%83%87%E3%83%BC%E3%82%BF
#%E5%8D%97%E6%A5%B5%E5%A4%A7%E9%99%B8
#%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF

#URLデコード:  パーセント文字 => 日本語
cat nkf_test3.txt | nkf -w --url-input > nkf_test4.txt

#変換結果を表示
cat nkf_test4.txt
#ベルギー
#幸福
#ジョージ・ワシン%
#トン
#ジャック・バウア%
#ー
#ウィキデータ
#南極大陸
#コンピュータ
#どうも、「%」が残っている、、変換に失敗しているっぽい。

#こっちが正解っぽい。
cat nkf_test3.txt | tr % = | nkf -WwmQ  > nkf_test5.txt

#変換結果を表示
cat nkf_test5.txt
#ベルギー
#幸福
#ジョージ・ワシントン
#ジャック・バウアー
#ウィキデータ
#南極大陸
#コンピュータ

どうも、nkfコマンドは、出力文字列が76文字を超えると、勝手に改行が挿入されるらしい。

76文字を超える文字列では、nkf -w --url-inputではうまく変換できない。

そういう場合には、tr % = | nkf -WwmQを使うと良い。

まとめ

「文字コード変換」という悩ましい問題をまとめてみた。

ファイル数が1つあるいは少ない場合には、 例えば、「BOM付きにする」とかの簡単な変換であれば、 CotEditor などのテキストエディターを使って、 エンコードを変更するのが手っ取り早い。

参考資料

kazmax.zpp.jp

http://feynmanino.watson.jp/2737_nkf.htmlfeynmanino.watson.jp

nalab.mind.meiji.ac.jp

e-words.jp

blog.offline-net.com

blue-red.ddo.jp

www.ryotosaito.com

*1:SBCS: Single-Byte Character Set

*2:DBCS: Double-Byte Character Set

*3:UCS Transformation Format 8

*4:UCS/Unicode Transformation Format 16

*5:Universal Coded Character Set

*6:https://osdn.net/projects/nkf/