今回は、Shift_JIS と utf-8 の変換などについて扱います。
[目次]
文字コード
以降で扱うために必要な、文字コードの知識・並びに Linux の標準文字コードである utf-8 を簡単に説明します。
あまり詳しくないため、その辺はご容赦ください。
xxd で実験してみる
# 16 進数ダンプ等をしてくれます $ man xxd xxd - make a hexdump or do the reverse. ...
英語と日本語を試しに xxd に突っ込んでみます。
2**8 = 16 * 16 なので、16 進数2文字分で 1 バイトを表します。
# 簡単な例 $ echo a | xxd -p 610a $ echo あ | xxd -p e381820a
行末に共通している 0a は、Linux での改行コード(LF)です。
それを除いて表示すると、以下のように「a」は1バイト、「あ」は 3 バイトで表されていることがわかります。
$ printf a | xxd -p 61 $ printf あ | xxd -p e38182
バイナリで表示するには、以下のように -b オプション(binary)をつけてあげます。
$ printf a | xxd -b 00000000: 01100001 a
元に戻す
標準の echo を使うと簡単にできます。
$ echo -e '\x61' a $ echo -e '\xE3\x81\x82' あ
1バイトずつチェック
# 基数を変換 $ echo -e '61\nE38182' | sed '1iibase=16; obase=2' | bc 1100001 111000111000000110000010 # 1 バイトずつに区切って整形して表示 $ echo -e '61\nE38182' | sed '1iibase=16; obase=2' |\ bc | xargs printf "%24s\n" | sed -r 's/.{8}/& /g' 1100001 11100011 10000001 10000010
わかること(調べてわかったこと)
- UTF-8 は可変長
- 「a」は1バイト (ASCII 文字)
- ASCII 文字列は、7 ビット分だけ埋まっている。
- 残り1ビットは 0 が自動で埋まる??
- 「あ」は 3バイト
- 先頭(1バイト目)は「1110」で始まる
- 続く中身に関しては、「10」で始めることで区別
- 上記は、ASCII の先頭が「0」であることと差別化できており区別可能
2進数から文字列を復元
# まず、解析に使いたいバイナリデータを作成する $ echo 'aあ' | xxd -b | awk '{$1=""; print}' | tr -dc '01' 0110000111100011100000011000001000001010 # 16 進数に変換する ## obase が先、ibase が後 ### ibase を先に書くと、obase=16 の 16 が2進数として解釈されていまう $ echo '0110000111100011100000011000001000001010' |\ sed '1iobase=16; ibase=2' | bc 61E381820A ### 失敗した例 $ echo '0110000111100011100000011000001000001010' |\ sed '1iibase=2; obase=16' | bc 1111012012101212001022112 # xxd -p -r: 16 真数を羅列したテキストを読んでデコードする $ echo '0110000111100011100000011000001000001010' |\ sed '1iobase=16; ibase=2' | bc | xxd -p -r aあ
nkf
Shift_JIS のファイルを UTF-8 に変換する
基本的には、nkf -wLux
を使います
# 普通に cat してみると、文字化けする $ cat shift_jis_test.txt Shift_JIS �̃e�X�g�ł� �V�t�g�W�X�e�X�g ����ɂ��͐��E # nkf コマンドを使う $ nkf -wLux shift_jis_test.txt Shift_JIS のテストです シフトジステスト こんにちは世界
オプションについて簡単に説明しておきます。
- -Lu は、CRLF をラインフィード(LF)だけに変換する
- -w は、テキストを UTF-8 に変える
- -x は、カタカナが半角になるのを防止する
UTF-8 のファイルを Shift_JIS に変換する
nkf の -s オプションなどを使います。
$ echo 吾輩は猫である。 | nkf -sLwx ��y�͔L�ł���B $ echo 吾輩は猫である。 | nkf -sLwx | nkf -wLux 吾輩は猫である。
- -s は、Shift_JIS への変換
- -Lw は、LF から CRLF への変換
おまけ
まとめ
- Shift_JIS to UTF-8 変換には
nkf -wLux
を使う xxd -p
で 16 進数変換する(-b で 2 進数)xxd -p -r
で 16 進数から文字に戻す- 数字の基数の変換では、bc を使う
echo 'obase=2; 3' | bc
おまけ:アルファベットは大文字で
基本的に 16 進数中のアルファベットは大文字で表すのが吉
# a, あ の UTF-8 の文字コード(16 進数)を2進数に戻したときの例 ## なぜか「あ」だけ変換されなかった $ echo -e '61\ne38182' | sed '1iibase=16; obase=2' | bc 1100001 0 ## e を E に変更したらうまくいった $ echo -e '61\nE38182' | sed '1iibase=16; obase=2' | bc 1100001 111000111000000110000010
bc の仕様か?
おわりに
今回しらべる中で、文字コードについて少し理解が深まった気がします。