AWK : 记录文件数据处理的利器
这篇文章介绍 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() } // 只执行一次, 多用于清理工作。
有了这样的框架, 记录文件的数据处理还有多少困难呢? 由于 AWK 特殊的程序处理方式, 特别适合于从筛选满足条件的记录行。
例子一:
某个 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 选项设置。
例子二: 假设有这样的数据文件 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
例子三: 找出当前目录及子目录下的所有 .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 / Python 这样重型的武器, 连 C 都不算轻量级了。
一个简单的 awk 程序: 计算 /etc/passwd 第三个字段的和数。
使用: awk -f calc.awk /etc/passwd
BEGIN { FS=":" total=0 } { if ($3 < 1000000) { total += $3 num[NR] = $3 } } END { print "ARGC=", ARGC; for(k in ARGV) { print k, "=", ARGV[k]; } print "File: ", FILENAME for (i=1; i<=FNR; i++) { printf("%d %s ", num[i] , (i==FNR) ? "" : "+") } print " = ", total }