awk使用字段操作符$来指定字段。在该操作符后面跟着一个数字或变量,用于标识字段的位置。"$1" 表示第一个字段, "$2" 表示第二个字段等等。"$0 "表示整个输入记录。下面的例子显示了第一个字段是姓,第二个字段是名字,后面是电话号码。
$ awk '{ print $2,$1,$3 }' names
Robinson John 666-555-1111
$1表示名字, $2表示姓,而$3表示电话号码。Print语句中分隔每个参数的逗号使得输入的各值之间有一个空格(随后,我们将讨论输出字段分隔符(OFS) ,它的值中输出的逗号默认为空格)。在这个例子中,一个输入行包含3个字段:在名字和姓之间有一个空格,在姓和电话号码之间有一个制表符。如果想将姓和名字结合起来作为一个字段,可以通过显式地指定字段分隔符走的只识别制表符。这样, awk将只识别该记录中的两个字段。
可以用任何计算值为整数的表达式来表示一个字段,而不只是用数字和变量。
$ echo a b c d | awk 'BEGIN { one = 1; two = 2 }
> { print $(one + two) }'
C
可以在命令行中使用-F选项改变字段的分隔符。下面的例子将字段分隔符修改为制表符。
$ awk -F"\t" '{ print $2 }' names
666-555-1111
"\t" 是表示一个实际的制表符的转义序列,它应由单引号或双引号包围着。下面两个地址记录中的字段是由逗号分隔的。
$ cat names
John Robinson, Koren Inc.,978 4th Ave.,Boston,MA 01760,696-0987
Phyllis Chapman, GVE Corp.,34 Sea Drive, Amesbury,MA 01881,879-0900
$ cat blocklist.awk
# blocklist.awk -用块格式打印姓名和地址
# 输入文件一名字、公司、街道、城市、州和邮编、电话
{ print "" # output blank line
print $1 # name
print $2 # company
print $3 # street
print $4, $5 # city, state zip
}
第一个print语句指定一个空串("") (记住print 本身输出当前行)。这种安排使得在报告中的记录由空格隔开。我们可以执行这个脚本并使用下面的命令指定字段分隔符为逗号:
$ awk -F,-f blocklist.awk names
John Robinson
Koren Inc.
978 4th Ave.
Boston MA 01760
Phyllis Chapman
GVE Corp.
34 Sea Drive
Amesbury MA 01881
在脚本中指定域分隔符是一个好的习惯并且是非常方便的。可以通过定义系统变量FS来改变字段分隔符。因为这个必须在读取第一行之前执行,所以必须在由BEGIN规则控制的操作中指定这个变量。
BEGIN { FS="," }
我们程序中使用它来打印出姓名和电话号码。
$cat phonelist.awk
# phonelist.awk -打印姓名和电话号码
# 输入文件一名字、公司、街道、城市、州和邮编、电话
BEGIN { FS = "," } #用逗号分割字段
{ print $1 ", " $6 }
注意,我们在脚本中使用空行未改善可读性。在print语句的两个输出字段之间插入逗号和一个空格。这个程序脚本可以通过以下命令行来执行:
$ awk -f phonelist.awk names
John Robinson, 696-0987
Phyllis Chapman, 879-0900
这些给了你一个关于如何使用awk来处理可识别的结构化数据的基本概念。这个程序脚本用来输出所有的输入行,但我们可以编写匹配规则来修改这个操作符使得只打印出特定的名字或地址。因此,如果我们有一个长的名字列表,我们可以仅选择居住在特定州的人名。我们可以编写为:
/MA/ {print $1 ", " $6}
这里的MA于马萨诸塞州邮政局的缩写相匹配。然而,MA也可能为一个公司的名字或其他地方的名字相匹配,其中在这些公司的名字或其他地方的名字中包含字母"MA" .我们可以测试匹配指定的字段。使用(~) 操作符可以测试一个字段的正则表达式:
$5 ~ /MA/{ print $1 ", " $6 }
可以使用组合符号(!~)来反转这个规则的意义。
$5 !~ /MA/ { print $1 ", " $6 }
这个规则将与所有其第五个字段不包含"MA"的记录相匹配。一个更有挑战性的模式匹配是仅与长途电话号码相匹配。下面的正则表达式查找一个区域代码。
$6 ~ /1?(-|□)?\(?[0-9]+\)?(□|-)?[0-9]+-[0-9]+/
这个规则和下列的形式相匹配:
707-724-0000
(707) 724-0000
(707)724-0000
1-707-724-0000
1 707-724-0000
1 (707)724-0000
这个正则表达式可以分段进行解释。"1?"表示出现零个或一个1; "(-|□)?"表示在随后的位置上查找一个连字符或一个空格,或什么也没有; "\(?"表示查找零个或一个左括号;反斜杠能够防止将"("解释为用于分组的元字符; "[0-9]+"表示查找一个或多个数字;注意我们采用了简便的方法,仅指定一到多位数字,而不是精确地指定3位数字。在随后的位置,我们查找一个可选的右括号,接着查找一个空格或一个连字符,或什么也没有。然后用" [0~9]+"查找一到多位数字,随后跟一个连字符,最后跟一到多位数字。
--------------------------------------分割线 --------------------------------------
--------------------------------------分割线 --------------------------------------