2010年9月23日木曜日

AWKでバイナリ出力する方法(mawk, Gawk専用) - AWK

AWKの入出力とコマンド実行機能
○Gawk on Windows ○Gawk ○mawk32 ○Mawk ×awk
AWKでバイナリファイルを扱う方法について調べてみました。
その結果、mawkとGawkでは、バイナリコードを書き出す事が出来る事が分かりました。

o バイナリファイルを作る事が出来る処理系は
   + Gawk on Windows 3.1.7
   + Gawk for Windows 3.1.6
   + mawk MBCS (32bit版) 1.3.3 -- 書式"%c"の1文字出力のみ対応
   + Mawk for Windows 1.3.3 -- 書式"%c"の1文字出力のみ対応

o バイナリファイルを作る事が出来ない処理系は
   + original = the one true awk(updated May 1, 2007)


**** 手順
o mawkとGawkの両方で使用出来る方法
   + 方法1。バイナリモードにして、printf("%c", 文字コード);
   + 方法2。バイナリモードにして、v = sprintf("%c", 文字コード); printf("%c", v);

o Gawkのみで使用出来る方法
   + 方法3。バイナリモードにして、"\x12"形式の文字列として書き、printf("%s", v);で一括出力
   + 方法4。バイナリモードにして、"\x12"形式の文字列として書き、print文で一括出力

o おまけ。使用出来なかった方法
   + バイナリコードに対する文字列の連結。v = v sprintf("%c", i);


** 方法1。バイナリモードにして、printf("%c", 文字コード);
○Gawk on Windows ○Gawk ○mawk32 ○Mawk ×awk
o 実行コマンド(= gawk の部分は、各処理系に置き換えます。)
--------
gawk -v BINMODE=3 -f a.awk > out.bin
--------

o AWKプログラム
--------
BEGIN {
  for (i = 0; i < 256; ++i) {
    printf("%c", i);
  }
}
--------

o 実行コマンドの中で、変数 BINMODEに 2 もしくは 3 を指定するのがポイントです。
o 行末のセミコロンは、C言語の書き方に合わせました。無くても動きます。


** 方法2。バイナリモードにして、v = sprintf("%c", 文字コード); printf("%c", v);
○Gawk on Windows ○Gawk ○mawk32 ○Mawk ×awk
o 実行コマンド(= gawk の部分は、各処理系に置き換えます。)
--------
gawk -v BINMODE=3 -f a.awk > out.bin
--------

o AWKプログラム
--------
BEGIN {
  for (i = 0; i < 256; ++i) {
    v = sprintf("%c", i);
    printf("%c", v);
  }
}
--------



** 方法3。バイナリモードにして、"\x12"形式の文字列として書き、printf("%s", v);で一括出力
○Gawk on Windows ○Gawk ×mawk32 ×Mawk ×awk
o 実行コマンド(= gawk の部分は、各処理系に置き換えます。)
--------
gawk -v BINMODE=3 -f a.awk > out.bin
--------

o AWKプログラム
--------
BEGIN {
  v = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";
  printf("%s", v);
}
--------

o \x12の書き方と文字を混在させる場合は、注意が必要です。
   + 16進数値と同じ文字が後ろに続くと、mawk以外では予想外の動きをしました。
o Gawk以外では、一部の文字コード出力に失敗します。
   + mawkは、0x00の出力に失敗します。
   + オリジナルは、変数 BINMODEをサポートしていません。
      + 0x00の出力失敗の他に、Windows版では常に 0x0A -> 0x0D0A変換を行います。


** 方法4。バイナリモードにして、"\x12"形式の文字列として書き、print文で一括出力
○Gawk on Windows ○Gawk ×mawk32 ×Mawk ×awk
o 実行コマンド(= gawk の部分は、各処理系に置き換えます。)
--------
gawk -v BINMODE=3 -f a.awk > out.bin
--------

o AWKプログラム
--------
BEGIN {
  ORS = ""; # print文の行区切り文字を無しに設定
  v = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";
  print v;
}
--------

o \x12の書き方と文字を混在させる場合は、注意が必要です。
   + 16進数値と同じ文字が後ろに続くと、mawk以外では予想外の動きをしました。
o Gawk以外では、一部の文字コード出力に失敗します。
   + mawkは、0x00の出力に失敗します。
   + オリジナルは、変数 BINMODEをサポートしていません。
      + 0x00の出力失敗の他に、Windows版では常に 0x0A -> 0x0D0A変換を行います。


** 出力結果の確認方法
o バイナリエディターによる目視確認と、Windowsのファイル比較コマンド(fc /B ファイル1 ファイル2)を併用して行いました。
o 00からFFまで、綺麗に並んでいたら成功です。


**** 確認した処理系
o Gawk on Windows 3.1.7
o Gawk for Windows 3.1.6
o mawk MBCS (32bit版) 1.3.3 -- 書式"%c"の1文字出力のみ対応
o Mawk for Windows 1.3.3 -- 書式"%c"の1文字出力のみ対応
o original = the one true awk(updated May 1, 2007) -- 非対応


==
関連ページ:
    ▼AWKの入出力関数とコマンド実行機能▼ABC順
    ▼AWKプログラムを書く▼ABC順
    ▼AWK
    ▼制作メモ
    > AWKでバイナリ入力する方法(Gawk専用)
    改行コード。Windows / UNIX / Mac の違いについて
    GawkでUTF-8のファイルを読み込む時の注意点
    +
    AWKプログラムの中で、8進数や16進数を使う方法
    BEGIN = 最初に実行する
    BINMODE = バイナリモードで読み書きする(mawk,Gawk専用)
    ORS = printを使って出力する時の改行文字
    sprintf = 文字列を組み立てる
(2010年9月27日変更。文字列に埋め込む例の説明で0x12から\x12に変更)
(2010年9月23日追加。出来なかった方法)