Linuxコマンドだけでなんとかしたい!
バイナリファイルのダンプ結果を2進数で表示させたいときがありました(linuxコマンドのみで)。
その時にやった内容を紹介します。
(他にいい方法があるのかもしれません。)
まず、以下のようなシェルスクリプトを用意。
hex2bin.sh
#!/bin/bash
hexdump -v -e '/1 "%02X\n"' $1 | awk '{print substr($1,1,1) " " substr($1,2,1)}' | awk -f hex2bin.awk
説明
まず最初の hexdumpコマンドで1バイト単位で出力します。
hexdump -v -e '/1 "%02X\n"' $1
出力例
$ hexdump -v -e '/1 "%02X\n"' file
7F
45
4C
46
02
01
01
00
$
で、この出力結果を awkにわたしてあいだに空白を入れます。
$ hexdump -v -e '/1 "%02X\n"' file | awk '{print substr($1,1,1) " " substr($1,2,1)}'
7 F
4 5
4 C
4 6
0 2
0 1
0 1
0 0
$
この出力結果をまたawkにわたします。今度は -f オプションで以下のスクリプトを指定します。
hex2bin.awk
function hex2bin(shex) {
bins["0"] = "0000";
bins["1"] = "0001";
bins["2"] = "0010";
bins["3"] = "0011";
bins["4"] = "0100";
bins["5"] = "0101";
bins["6"] = "0110";
bins["7"] = "0111";
bins["8"] = "1000";
bins["9"] = "1001";
bins["A"] = "1010";
bins["B"] = "1011";
bins["C"] = "1100";
bins["D"] = "1101";
bins["E"] = "1110";
bins["F"] = "1111";
return bins[shex];
}
{
print hex2bin($1) " " hex2bin($2);
}
これで以下のような出力ができます。
sample.txt
0111 1111
0100 0101
0100 1100
0100 0110
0000 0010
0000 0001
出力結果を戻してみる
ここまでできたので、せっかくだからlinuxの標準コマンドだけでバイナリ形式に戻してみます。
以下のようなawkスクリプトを用意してみました。
bin2hex.awk
function bin2hex(sbin) {
hex["0000"] = "0";
hex["0001"] = "1";
hex["0010"] = "2";
hex["0011"] = "3";
hex["0100"] = "4";
hex["0101"] = "5";
hex["0110"] = "6";
hex["0111"] = "7";
hex["1000"] = "8";
hex["1001"] = "9";
hex["1010"] = "A";
hex["1011"] = "B";
hex["1100"] = "C";
hex["1101"] = "D";
hex["1110"] = "E";
hex["1111"] = "F";
return hex[sbin];
}
{
printf "echo -en \"\\x%c%c\" >> hoge.bin\n",bin2hex($1),bin2hex($2)
}
これで
0111 1111
という文字列が
echo -en "\x7F" >> hoge.bin
というechoコマンドに変換されます。
以下のように、てきとうなファイル名にリダイレクトをして、そのファイルを実行するとバイナリファイルが出力されます。
$ awk -f bin2hex.awk sample.txt > text2bin.sh
$ bash text2bin.sh