使用 Awk 的小筆記

因為需要把 link 出來的執行檔切到 .bss section 為止, 以便做成比較小的載入檔, 所以我們一直需要一個把大檔案切小的功能. 反正 .bss 是不需要初值的, 根本不用儲存那一塊.

原先我們的公用 makefile 是比較陽春的, 為了吃進參數方便, 在 makefile 中 run-time 去編譯一個 c++ 的小程式, 以便在 Linux 和 Cygwin 的環境都可以用.

不過最近遇到問題了, 假如某台 Linux server 不適合灌 development tool chain, 那根本就不能 make 了. 為了解決這個問題, 我決定用 gawk 來做它.

Gawk 來自 AT&T 的 awk, 加了 G 字頭之後, 就表示它是 Gnu 家族的 freeware 成員. 另外還有個 Nawk, N 字頭表示 New (新版).

Gawk  沒有型別定義, 變數可能是 string, 也可能是 number,  完全看場合而定. 它可以寫成一行文 gawk {}, 或是讀一個批次檔來執行 gawk -f batchfile.

因為一行文已不符合我的需求, 所以我這次是用檔案.

x = $1

就把參數 1 抓進來了. $2 表示參數 2, 依此類推. 但是 $0 表示一整行的所有參數.

那第二行怎麼辦呢?

用 getline, getline 之後, 原來的 $0, $1,…就都變成與下一行的對照關係了.

依據這樣的參數, 就可以計算出真正需要的 file size 有多大.

不過另外有一個問題. Gawk 有三角函數的計算能力, 我卻找不到計算 16 進位的加減法功能? 這時當然是上網找打手. 在 http://os.cqu.edu.au/cgi-bin/info/info2html.cgi?(gawk)Strtonum%20Function 有現成的 sting 到 number 轉換程式.

Gawk 是可以呼叫 function 的:

x = abs($1)

function abs(str)

{

}

因為 awk 沒有型別,  所以 function 的參數就直接是 variable. 我引用的這個網址使用了很漂亮的 index 技巧, 有興趣的人可以參考這個寫法.

if ((k = index(“abcdef", c)) > 0)

 k += 9

如此就把輸入 c = a, k = 9+ 1 (1 是 index = 1) 的計算給求出來了.

Gawk 還可以呼叫 system() 函數, 有這個功能就可以在 Gawk 裡面做很多事情. 總之, 這樣就可以把我要的 file size 計算出來了.

那麼怎麼砍檔案呢? 網路上有各式各樣的講法. 有人說可以寫一個 truncate function、有人說可以用 (c)split、有人說可以用 cut.  

split 會產生一大堆相同 size 的檔案, 而且也只適合於 text (line-based) 的文檔.

Binary 檔的切割, 用 cut 也不正確. 如果用 cut –help 去看, 就知道 cut -b 並不是要 cut 幾個 byte 出來, 而是每行 cut 這麼多 bytes!

所以用 head 或是 tail 才對, 他們才是適合切割 binary 檔的.

head -c 1000 BigFile > SmallFile

這樣就行了, 那個 1000 就用 gawk 來幫忙算. 如此即可以免去即時編譯 c++ 的困擾.

gawk 的使用手冊可以參考這個網址, 我都是用到多少才去了解多少, 沒手冊還真是不行.

http://www.grymoire.com/Unix/Awk.html