1.4 选择
Awk的样式很适合将输入行中感兴趣的行选取出来,用于后续处理。由于不含动作的样式会将所有匹配该样式的行都打印出来,因此很多Awk程序仅仅就包含一个样式。本节给出一些有用的样式。
通过比较来选择
这个程序使用了一个比较样式,将时薪超过20美元的员工记录选择出来,即把第二个域大等于20的行选择出来:
$2 >= 20
emp.data作为输入,输出是:
Beth 21 0
Mark 25 20
Mary 22.50 22
通过计算来选择
$2 * $3 > 200 { printf("$%.2f for %s\n", $2 * $3, $1) }
这个程序将收入超过200的员工收入及其姓名打印出来
$500.00 for Mark
$495.00 for Mary
$306.00 for Susie
通过文本来选择
除了上面的数字测试之外,还能选择包含特定单词或短语的行。下面的程序打印第一个域为 Susie 的行:
$1 == "Susie"
其中的操作符连等号 == 用于测试是否相等。你也能用正则表达式(regular expressions)作为样式来进行文本匹配。下面的程序会打印出所有包含 Susie (不管Susie在行的哪个位置)的行:
/Susie/
输出结果是
Susie 17 18
正则表达式可用于非常非常复杂的文本匹配,附录A.1.4有完整的说明。
样式的组合
多个样式可以使用括号以及逻辑运算符 && 、|| 、 ! (分别代表于、或、非)组合起来。如下程序
$2 >= 20 || $3 >= 20
将 $2 最少为 20 或者 $3 最少为20的行打印出来,两个条件都符合的行也只会打一次:
Beth 21 0
Mark 25 20
Mary 22.50 22
可以对比下面这个程序,包含两个样式:
$2 >= 20
$3 >= 20
其中两个条件都符合的行,会打印两次。
Beth 21 0
Mark 25 20
Mark 25 20
Mary 22.50 22
Mary 22.50 22
另外,下面这个程序
!($2 < 20 && $3 < 20)
与前面第一个程序的逻辑是一样的,不过可读性会差。
数据校验
现实的数据总是包含错误。数据校验指的是:检查数据格式是否正确,取值是否合理。Awk就是用来做数据校验的极佳工具。
数据校验基本上是反着来的:它不是把包含所需属性的行打印出来,而是打印其中可疑的行。下面的程序使用比较样式,对emp.data每行进行五个合理性测试:
NF != 3 { print $0, "number of fields is not equal to 3" }
$2 < 15 { print $0, "rate is too low" }
$2 > 25 { print $0, "rate exceeds $25 per hour" }
$3 < 0 { print $0, "negative hours worked" }
$3 > 60 { print $0, "too many hours worked" }
如果没有错误,就没有输出。(符合Unix哲学)
BEGIN 和 END
还有两个特殊的样式。BEGIN 样式匹配第一个输入文件的第一个行被读入之前,而 END 样式匹配最后一个文件的最后一行处理完之后。下面这个使用 BEGIN 来打印一个表头;为了排版好看,其中的空格数量是经过计算的:
BEGIN { print "NAME RATE HOURS"; print "" }
{ print }
输出为:
NAME RATE HOURS
Beth 21 0
Dan 19 0
Kathy 15.50 10
Mark 25 20
Mary 22.50 22
Susie 17 18
可以将多个语句放在同一行内,使用分号隔开。注意 print "" 会打印一个空行,这与单单一个 print 差别很大,后者是打印当前输入行。(不过看起来放在BEGIN里面效果一样)