這篇文章介紹 AWK 。 它是記錄檔案資料處理的利器。為什麼會這樣呢?
AWK 隱式地提供了如下功能:
(1) 開啟每一個檔案並讀取每一行;對於每一行,根據欄位分隔符號和行分隔字元分割行和欄位,並儲存檔案、行、欄位資訊;
(2) 對每一行進行條件判斷和模式比對,若結果為真則執行相應操作;
(3) 實際上,提供了記錄檔案資料處理的架構, 只需要程式員填寫條件及操作即可。
for each file
for each line
for each pattern
if (IsConditionTrue(line, pattern)) do givenOperation
AWK 程式結構:
BEGIN { init() } // 只執行一次, 多用於初始化;
PATTERN1 { OPERATION1 } // 對於每個檔案的每一行進行判斷, 若模式PATTERN1 為真, 則執行操作 OPERATION1
...
PATTERNn { OPERATIONn } // 對於每個檔案的每一行進行判斷, 若模式PATTERNn 為真, 則執行操作 OPERATIONn
END { clean() } // 只執行一次, 多用於清理工作。
有了這樣的架構, 記錄檔案的資料處理還有多少困難呢?
例子:
某個 src.java 檔案中含有如下代碼:
public final static String CLUNUMREPORT_ALIAS = "clunumrep";public final static String CLUNUMREPORT_PREFIX = "clunumrep.";public final static String TOTAL_KEY = "total";public final static String STOPPED_KEY = "stopped";public final static String RUNNING_KEY = "running";public final static String DESTROYED_KEY = "destroyed";public final static String NEW_KEY = "new";public final static String REPORT_NUM_HOLE_KEY_RES="REPORT_NUM_HOLE_KEY";public final static String REPORT_MON_CIN_AVG_KEY_RES="REPORT_MON_CIN_AVG_KEY";public final static String REPORT_MON_INTER_KEY_RES="REPORT_MON_INTER_KEY";public final static String VM_INTER_KEY_RES="VM_INTER_KEY";
現在我期望能夠將類似 TOTAL_KEY = "total"; 的值對提取出來以方便查看。 用 AWK 怎麼做呢 ?
awk ' NF==5 { print $5 } ; NF==7 { print $5, $6, $7} ' src.java > result.txt
OK . 就這麼簡單。 NF==5 { print $5 } 表示 行的欄位數目為 5 時列印第 5 個欄位。 預設以空白符為欄位分割符。 可以通過 -F 選項設定。
例子2: 假設有這樣的資料檔案 src.txt :
name no height this last zhangsan 1 159 95 92 lisi 3 167 88 91 wangwu 6 172 82 84
this 表示此次的成績, last 表示上次的成績。 要找出成績進步的同學,也就是說 this 值大於 last . 只要
awk ' $4 > $5 { print } ' src.txt
例子3: 找出目前的目錄及子目錄下的所有 .java 檔案中含有 vm_monitor 模式字串的記錄行,並列印檔案、行資訊。
find . -name '*.java' | xargs awk ' $0 ~ /vm_monitor/ { printf "%s : Line %s :\n%s \n" , FILENAME, FNR, $0 } ' | sed 's/^[[:space:]]\{1,\}/ /' | fmt -w 75
夠快捷的吧 ? 所以說, 掌握一些重要的 Linux 工具 (Windows 下也可獲得!cygwin ), 日常任務其實不需要像 Java 這樣重型的武器, 連 C 都不算輕量級了。