處理 Multi-line 記錄

AWK每次從資料檔中只讀取一筆Record, 進行處理. AWK係依照 其內建變數 RS(Record Separator) 的定義將檔案中的資料分隔成 一筆一筆的Record. RS 的預設值是 "\n"(跳行符號), 故平常AWK中一行資料就是一筆 Record. 但有些檔案中一筆Record涵蓋了數行資料, 這種情況下不能再以 "\n" 來分隔Records. 最常使用的方法是相鄰的Records之間改以 一個空白行 來隔開. 在AWK程式中, 令 RS = ""(空字串)後, AWK把會空白行當成來檔案 中Record的分隔符號. 顯然AWK對 RS = "" 另有解釋方式,簡略描述 如下, 當 RS = "" 時 :
  1. 數個併鄰的空白行, AWK僅視成一個單一的Record Saparator. (AWK不會於兩個緊併的空白行之間讀取一筆空的Record)
  2. AWK會略過(skip)檔首或檔末的空白行. 故不會因為檔首或檔末 的空白行,造成AWK多讀入了二筆空的資料.
請觀察下例,首先建立一個資料檔 week.rpt如下: 張長弓 GNUPLOT 入門 吳國強 Latex 簡介 VAST-2 使用手冊 mathematica 入門 李小華 AWK Tutorial Guide Regular Expression 該檔案檔首有數列空白行, 各筆Record之間使用一個或數個空白行 隔開. 讀者請細心觀察, 當 RS = "" 時, AWK讀取該資料檔之方式. 編輯一個AWK程式檔案 make_report如下: awk ' BEGIN { FS = "\n" RS = "" split( "一. 二. 三. 四. 五. 六. 七. 八. 九.", C\_Number, " " ) } { printf("\n%s 報告人 : %s \n",C_Number[NR],$1) for( i=2; i { >}= NF; i++) printf(" %d. %s\n", i-1, $i) } ' $ 執行 $ make_report week.rpt 螢幕產生結果如下: 一. 報告人 : 張長弓 1. GNUPLOT 入門 二. 報告人 : 吳國強 1. Latex 簡介 2. VAST-2 使用手冊 3. mathematica 入門 三. 報告人 : 李小華 1. AWK Tutorial Guide 2. Regular Expression 說明:
  1. 本程式同時也改變欄位分隔字元( FS= "\n"), 如此一筆資料 中的每一行都是一個field. 例如 : AWK讀入的第一筆 Record 為 張長弓 GNUPLOT 入門 其中 $1 指的是"張長弓", $2 指的是"GNUPLOT 入門"
  2. 上式中的C\_Number[ ]是一個陣列(array), 用以記錄中文數字. 例如 : C\_Number[1] = "一", C\_Number[2] = "二" 這過程使用AWK字串函數 split( ) 來把中文數字放進陣列 Number[ ]中. 函數 split( )用法如下 : split( 原字串, 陣列名稱, 分隔字元(field separator) ) : AWK將依所指定的分隔字元(field separator)分隔原字串成一個個 的欄位(field), 並以指定的 陣列 記錄各個被分隔的欄位