ddでAB(上下1Byte)入れ替え

今回もddです。AB入れ替え(上下1Byte入れ替え)します。

入力ファイルとして、数値1~10のバイナリを以下のようにして作成。

takk@deb9:~/tmp$ seq 10 | perl -ne 'print chr' > in.bin
takk@deb9:~/tmp$ od -tx1 -An in.bin
 01 02 03 04 05 06 07 08 09 0a
takk@deb9:~/tmp$ 

2Byte毎に上下1Byteを入れ替えます。conv=swabを指定するだけなので非常に簡単です。

takk@deb9:~/tmp$ cat in.bin | dd conv=swab > out.bin
0+1 レコード入力
0+1 レコード出力
10 bytes copied, 0.000530802 s, 18.8 kB/s
takk@deb9:~/tmp$ od -tx1 -An out.bin
 02 01 04 03 06 05 08 07 0a 09
takk@deb9:~/tmp$ 

さて、dd以外のコマンドを使ってAB変換してみましょう。
sedでやってみます。

takk@deb9:~/tmp$ cat in.bin | sed 's/\(.\)\(.\)/\2\1/g'> out2.bin
takk@deb9:~/tmp$ od -tx1 -An out.bin
 02 01 04 03 06 05 08 07 09 0a
takk@deb9:~/tmp$ 

あれ、できないです。上記の行末の0aが改行コードなので、sedでは置換から除外されてしまいます。

セパレータを改行でなくNULLにする-zオプションを指定すれば、このデータなら変換できますが、

takk@deb9:~/tmp$ cat in.bin | sed -z 's/\(.\)\(.\)/\2\1/g'> out2.bin
takk@deb9:~/tmp$ od -tx1 -An out2.bin
 02 01 04 03 06 05 08 07 0a 09
takk@deb9:~/tmp$ 

-zオプションを使ったところで、NULL(0)の方が無視されてしまいます。

takk@deb9:~/tmp$ echo -ne "\x0\x1\x2\x3" >in2.bin
takk@deb9:~/tmp$ od -tx1 -An in2.bin
 00 01 02 03
takk@deb9:~/tmp$ cat in2.bin | sed -z 's/\(.\)\(.\)/\2\1/g' > out2.bin
takk@deb9:~/tmp$ od -tx1 -An out2.bin
 00 02 01 03
takk@deb9:~/tmp$ 

ということで、一旦テキストに変換してからバイナリに戻すことにします。
xxdコマンドを使うと、ダンプ時に簡単に上下1Byteを入れ替えてくれます。

takk@deb9:~/tmp$ cat in.bin | xxd -c2 -e | cut -d' ' -f2
0201
0403
0605
0807
0a09
takk@deb9:~/tmp$ 

そして、さらにxxdはダンプ結果をバイナリに戻すこともできるので、 -rオプションを使って戻してみます。

takk@deb9:~/tmp$ cat in.bin | xxd -c2 -e | cut -d' ' -f2 | xxd -r -p > out3.bin
takk@deb9:~/tmp$ od -tx1 -An out3.bin
 02 01 04 03 06 05 08 07 0a 09
takk@deb9:~/tmp$ 

やりたいことは簡単なのに、ワンライナー長すぎです。
まあやっぱり、AB入れ替えを使う機会があるなら、ddコマンドでいいですね。

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA