awk字段和引用的分离

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]+"查找一到多位数字,随后跟一个连字符。最后跟一到多位数字。

參考资料:http://www.linuxawk.com/communication/466.html

posted on 2017-07-08 08:53  ljbguanli  阅读(196)  评论(0编辑  收藏  举报