5. a w k中使用F S变量
如果使 用非空格符做域分隔符( F S)浏览文件,例如# 或:,编写这样的一行命令很容易, 因为使用F S选项 可以在命令行中指定域分隔符。

[Copy to clipboard] [ - ]

CODE:

$awk -F: '{print $0}' inputfile


使用a w k脚本时,记住设置F S变量是在B E G I N部分。如果不这样做, a w k将会发生混淆,不知道域分隔符是什么。
下述脚 本指定F S变量。脚本从/ e t c / p a s s w d文 件中抽取第1和第5域,通过分号“;”分隔p a s s w d文件域。第1域是帐号名,第5域是帐号所有者。
我 举的例子是第七个域:

[Copy to clipboard] [ - ]

CODE:

[sam@Linux_chenwy sam]$ awk -F: '{print $1,"\t",$7}' passwd
root     /bin/bash
bin      /sbin/nologin
daemon   /sbin/nologin
adm      /sbin/nologin
lp       /sbin/nologin
sync     /bin/sync
.................................


这是不 用脚本的,后面的结果省略

现使用 脚本如下:

[Copy to clipboard] [ - ]

CODE:

[sam@Linux_chenwy sam]$ cat passwd.awk
#!/bin/awk -f
#to call:passwd.awk /etc/passwd
#print out the first and seventh fields
BEGIN{
FS=":"}
{print $1,"\t",$7}


结果如 下:

[Copy to clipboard] [ - ]

CODE:

[sam@Linux_chenwy sam]$ chmod u+x passwd.awk
[sam@Linux_chenwy sam]$ ./passwd.awk passwd
root     /bin/bash
bin      /sbin/nologin
daemon   /sbin/nologin
adm      /sbin/nologin
lp       /sbin/nologin
sync     /bin/sync
.......................................


6.
a w k脚本传值
a w k脚本传值与向a w k一行命令传值方式大体相同,格式为:

[Copy to clipboard] [ - ]

CODE:

awk script_file var=value input_file


下述脚 本对比检查文件中域号和指定数字。这里使用了N F变量M A X, 表示指定检查的域号,使用双引号将域分隔符括起来,即使它是一个空格。
脚本如 下:

[Copy to clipboard] [ - ]

CODE:

[sam@Linux_chenwy sam]$ cat fieldcheck.awk
#!/bin/awk -f
#check on how many fields in a file
#name:fieldcheck.awk
#to call:fieldcheck MAX=n FS=<separator> filename
#
NF!=MAX{
print("line" NR " does not have " MAX "fields")}


如果NF中的值不等于最大MAX值,则打印出"哪一行的域总数不是max"

如果以/ e t c / p a s s w d作输入文件(p a s s w d文件有7个域),运行上述脚本。参数格式如下:

[Copy to clipboard] [ - ]

CODE:

[sam@Linux_chenwy sam]$ chmod u+x fieldcheck.awk
[sam@Linux_chenwy sam]$ ./fieldcheck.awk MAX=7 FS=":" passwd


正好7个域,如果改成6,就会显示不同结果,试试看?

使用前 面一行脚本的例子,将之转换成a w k脚 本如下:

[Copy to clipboard] [ - ]

CODE:

[sam@Linux_chenwy sam]$ cat name.awk
#!/bin/awk -f
#name:age.awk
#to call:age.awk AGE=n grade.txt
#print ages that are lower than the age supplied on the comand line
{if ($5<AGE)
print $0}


文本包 括了比实际命令更多的信息,没关系,仔细研读文本后,就可以精确知道其功能及如何调用它。
不要忘 了增加脚本的可执行权限,然后将变量和赋值放在命令行脚本名字后、输入文件前执行。

[Copy to clipboard] [ - ]

CODE:

[sam@Linux_chenwy sam]$ chmod u+x name.awk
[sam@Linux_chenwy sam]$ ./name.awk AGE=10 grade.txt
M.Tans 5/99 48311 Green 8 40 44
J.Lulu 06/99 48317 green 9 24 26


同样可 以使用前面提到的管道命令传值,下述a w k脚 本从d u命令 获得输入,并输出块和字节数。

[Copy to clipboard] [ - ]

CODE:

[root@Linux_chenwy sam]# cat duawk.awk
#!/bin/awk -f
#to call:du|duawk.awk
#prints file/direc's in bytes and blocks
BEGIN{
OFS="\t";
print "name" "\t\t","bytes","blocks\n"
print "==============================="}
{print $2,"\t\t",$1*512,$1}


使用du的结果如下

[Copy to clipboard] [ - ]

CODE:

[root@Linux_chenwy sam]# du
12      ./.kde/Autostart
16      ./.kde
8       ./.xemacs
4       ./sam
4       ./dir1
4       ./file6
184     .


执行:

[Copy to clipboard] [ - ]

CODE:

[root@Linux_chenwy sam]# du | ./duawk.awk
name                    bytes   blocks

===============================
./.kde/Autostart                                6144    12
./.kde                          8192    16
./.xemacs                               4096    8
./sam                           2048    4
./dir1                          2048    4
./file6                         2048    4
.                               94208   184



[Copy to clipboard] [ - ]

CODE:

OFS="\t";


是什么 意思了,好累,晚上再研究,谁解答一下更好


数 组
前面讲 述s p l i t函数时,提到怎样使用它将元素划分进一个数组。这里还有一个例子:

[Copy to clipboard] [ - ]

CODE:

[sam@Linux_chenwy sam]$ awk 'BEGIN {print split("123#456#789",myarray,"#")}'
3


实际上m y a r r a y数组为

[Copy to clipboard] [ - ]

CODE:

Myarray[1]="123"
Myarray[2]="456"
Myarray[3]="789"


数组使 用前,不必定义,也不必指定数组元素个数。经常使用循环来访问数组。下面是一种循环类型的基本结构:

[Copy to clipboard] [ - ]

CODE:

For (element in array ) print array[element]


对于记 录“ 1 2 3 # 4 5 6 # 6 7 8”,先使用s p l i t函数划分它,再使用循环打印各数组元素。操作脚本如下:

[Copy to clipboard] [ - ]

CODE:

[sam@Linux_chenwy sam]$ cat arraytest.awk
#!/bin/awk -f
#name:arraytest.awk
#prints out an array
BEGIN{
record="123#456#789";
split(record,myarray,"#")}
END{for (i in myarray) {print myarray[i]}}


要运行 脚本,使用/ d e v / n u l l作为输入文件。

[Copy to clipboard] [ - ]

CODE:

sam@Linux_chenwy sam]$chmod u+x arraytest.awk
[sam@Linux_chenwy sam]$ ./arraytest.awk /dev/null
123
456
789
[sam@Linux_chenwy sam]$


数 组和记录
上面的 例子讲述怎样通过s p l i t函数使用数组。也可以预先定义数组,并使用它与域进行比较测试,下面的例 子中将使用更多的数组。
下面是 从空手道数据库卸载的一部分数据,包含了学生级别及是否是成人或未成年人的信息,有两个域,分隔符为( #),文件如下:

[Copy to clipboard] [ - ]

CODE:

[sam@Linux_chenwy sam]$ cat grade_student.txt
Yellow#Junior
Orange#Senior
Yellor#Junior
Purple#Junior
Brown-2#Junior
White#Senior
Orange#Senior
Red#Junior
Red#Junior
Brown-2#Senior
Yellow#Senior
Red#Junior
Blue#Senior
Green#Senior
Purple#Junior
White#Junior


脚本功 能是读文件并输出下列信息。
1)
俱 乐部中Ye l l o wO r a n g eR e d级 别的人各是多少。
2 )
俱 乐部中有多少成年人和未成年人。
查看文 件,也许2 0秒内就会猜出答案,但是如果记录超过6 0个又 怎么办呢?这不会很容易就看出来,必须使用a w k脚本。
首先看 看a w k脚本,然后做进一步讲解。

[Copy to clipboard] [ - ]

CODE:

[sam@Linux_chenwy sam]$ cat belts.awk
#!/bin/awk -f
#name:belts.awk
#to call:belts.awk grade2.txt
#loops through the grade2.txt file and counts how many
#belts we have in (yellow,orange,red)
#also count how many adults and juniors we have
#
#start of BEGIN
#set FS and load the arrays with our values

#B E G I N
部分设置F S为符 号#,即域分隔符

BEGIN{FS="#"

#Load the belt colours we are interested in only
#
因为 要查找Ye l l o wO r a n g eR e d三 个级别。
#
然后 在脚本中手工建立数组下标对学生做同样的操作。
#
注 意,脚本到此只有下标或元素,并没有给数组名本身加任何注释。

belt["Yellow"]
belt["Orange"]
belt["Red"]
#end of BEGIN
#load the student type
student["Junior"]
student["Senior"]
}

##
初 始化完成后, B E G I N部分结束。记住B E G I N部分并没有文件处理操作。

#loop thru array that holds the belt colours against field-1
#if we have a match,keep a running total

#
现在 可以处理文件了。
#
首先 给数组命名为c o l o r,使用循环语句测试域1级别列是否
#
等于 数组元素之一(Ye l l o wO r a n g eR e d),
#
如果 匹配,依照匹配元素将运行总数保存进数组。

{for (colour in belt)
{if($1==colour)
belt[colour]++}}

#loop thru array that holds the student type against
#field-2 if we have a match,keep a runing total

#
同样 处理数组‘ S e n i o r _ o r _ j u n i o r’
#
浏览 域2时匹配操作满足,运行总数存入j u n i o rs e n i o r的匹配数组元素。

{for (senior_or_junior in student)
{if ($2==senior_or_junior)
student[senior_or_junior]++}}

#finished processing so print out the matches..for each array

#E N D
部分打印浏览结果,对每一个数组使用循环语句并打印它。

END{for (colour in belt )print "The club has ",belt[colour],colour,"Belts"

#
注意 在打印语句末尾有一个\符号,用来通知a w k(或 相关脚本)命令持续到下一行,
#
当输 入一个很长的命令,并且想分行输入时可使用这种方法。

for (senior_or_junior in student) print "The club has ",\
student[senior_or_junior],senior_or_junior,"student"}


运行脚 本前记住要加入可执行权限

[Copy to clipboard] [ - ]

CODE:

[sam@Linux_chenwy sam]$ chmod u+x belts.awk
[sam@Linux_chenwy sam]$ ./belts.awk grade_student.txt
The club has  3 Red Belts
The club has  2 Orange Belts
The club has  2 Yellow Belts
The club has  7 Senior student
The club has  9 Junior student