小ネタです。
久しぶりのワンライナーです。
ワンライナー
今回ご紹介するワンライナーはこちらです。
cat binary.txt | awk -F# '{print $1}' | grep -s "[0-9a-f]" | sed -e 's/^ *//g' -e 's/ *$//g' -e 's/\ /\\x/g' -e 's/^/\\x/g' -e 's/x/\\x/g' | xargs -I{} echo -en {} > HelloWorld.class
(10/12 追記)
@greymd さんのコメントを元にワンライナーを改良しました!だいぶすっきりしています。
cat binary.txt | awk -F# '{print $1}' | tr -dc [0-9a-f] | xxd -r -p > HelloWorld.class
(/追記)
テキストファイルに16進数で書いたバイト列を読み取ってバイナリファイルを作ってくれるというやつです。
ちょっとバイナリファイルを手打ちで作りたいなー、という需要が個人的にあったので作ってみました。
使い方
まずはインプットとなるbinary.txt
ファイルをテキストファイルとして準備します。1
ca fe ba be 00 00 00 34 00 1d 0a 00 06 00 0f 09
00 10 00 11 08 00 12 0a 00 13 00 14 07 00 15 07
00 16 01 00 06 3c 69 6e 69 74 3e 01 00 03 28 29
56 01 00 04 43 6f 64 65 01 00 0f 4c 69 6e 65 4e
75 6d 62 65 72 54 61 62 6c 65 01 00 04 6d 61 69
6e 01 00 16 28 5b 4c 6a 61 76 61 2f 6c 61 6e 67
2f 53 74 72 69 6e 67 3b 29 56 01 00 0a 53 6f 75
72 63 65 46 69 6c 65 01 00 0f 48 65 6c 6c 6f 57
6f 72 6c 64 2e 6a 61 76 61 0c 00 07 00 08 07 00
17 0c 00 18 00 19 01 00 0b 68 65 6c 6c 6f 20 77
6f 72 6c 64 07 00 1a 0c 00 1b 00 1c 01 00 0a 48
65 6c 6c 6f 57 6f 72 6c 64 01 00 10 6a 61 76 61
2f 6c 61 6e 67 2f 4f 62 6a 65 63 74 01 00 10 6a
61 76 61 2f 6c 61 6e 67 2f 53 79 73 74 65 6d 01
00 03 6f 75 74 01 00 15 4c 6a 61 76 61 2f 69 6f
2f 50 72 69 6e 74 53 74 72 65 61 6d 3b 01 00 13
6a 61 76 61 2f 69 6f 2f 50 72 69 6e 74 53 74 72
65 61 6d 01 00 07 70 72 69 6e 74 6c 6e 01 00 15
28 4c 6a 61 76 61 2f 6c 61 6e 67 2f 53 74 72 69
6e 67 3b 29 56 00 20 00 05 00 06 00 00 00 00 00
02 00 00 00 07 00 08 00 01 00 09 00 00 00 1d 00
01 00 01 00 00 00 05 2a b7 00 01 b1 00 00 00 01
00 0a 00 00 00 06 00 01 00 00 00 01 00 09 00 0b
00 0c 00 01 00 09 00 00 00 25 00 02 00 01 00 00
00 09 b2 00 02 12 03 b6 00 04 b1 00 00 00 01 00
0a 00 00 00 0a 00 02 00 00 00 03 00 08 00 04 00
01 00 0d 00 00 00 02 00 0e
これを、さきほどのワンライナーを使ってバイナリファイルに変換します。
cat binary.txt | awk -F# '{print $1}' | tr -dc [0-9a-f] | xxd -r -p > HelloWorld.class
これで、インプットに指定したbinary.txt
に記載されたバイト列からなるバイナリファイルを作ることができました。名前はHelloWorld.class
としています。
Javaのクラスファイルですので、java
コマンドで実行してみましょう。
$ java HelloWorld
hello world
ちゃんとjava
コマンドで読み取れましたね。
ちょっとした機能紹介
さて、このワンライナーですが、以下の2点を少し工夫しています。
- 任意の位置で改行できる(改行はアウトプットに反映されない)
- 行末にコメントを入れられる
このおかげで、
ca fe ba be # 最初はマジックナンバー
00 00 00 34 00 1d 0a 00 06 00 0f 09 00 10 00 11
08 00 12 0a 00 13 00 14 07 00 15 07 00 16 01 00
... 省略...
48 65 6c 6c 6f 57 6f 72 6c 64 # この部分にクラス名
2e 6a 61 76 61 0c 00 07 00 08 07 00 17 0c 00 18
00 19 01 00 0b
68 65 6c 6c 6f 20 77 6f 72 6c 64 # この部分に"hello world"
... 省略...
0a 00 00 00 0a 00 02 00 00 00 03 00 08 00 04 00
01 00 0d 00 00 00 02 00 0e
のように、行を良いところで区切ったりコメントを入れることによってアウトプットしたいバイナリファイルの内容を人間の目にも見やすく、また修正しやすくなっています。
作りたいバイナリファイルのフォーマットを確認しながら手打ちできたりもして何かと便利です。個人的に。
まとめ
byte[]
がマイブームです。
11/21 追記
このワンライナーを使ってBitmap画像を作ってみよう!という記事を書いて公開しました。
この記事で紹介したワンライナーがバイナリデータの勉強にとても便利に使えることが書かれていますので、ぜひ読んでみてください。
【バイナリファイル入門】Bitmapファイルを手書きで作って遊んでみる
-
これはこの記事の利用例のためにJavaの
HelloWorld.class
ファイルからxxd
コマンド使ったりしてバイト列部分だけを抽出したものです。さすがにこの量を手打ちはできません。 ↩