IT!
全部博文(84)
2013年(84)
分类: LINUX
2013-10-05 19:43:38
原文地址:管理脚本语言gawk--连载4 作者:顽主
调用gawk程序
当需要很多对模式和动作时,你可以编写一个gawk程序(也叫做gawk脚本)。在gawk程序中,你可以省略模式和动作两边的引号,因为在gawk程序中,模式和动作从哪开始和从哪结束时是很显然的。
你可以使用如下命令调用gawk程序:
gawk-fscriptfilename
此命令使gawk对文件filename执行名为script的gawk程序。
如果你不希望使用缺省的字段分隔符,你可以在f选项后面跟着F选项指定新的字段分隔符(当然你也可以在gawk程序中指定),例如,使用分号作为字段分隔符:
gawk-fscript-F";"filename
如果希望gawk程序处理多个文件,则把各个文件名罗列其后:
gawk-fscriptfilename1filename2filename3...
缺省情况下,gawk的输出将送往屏幕。但你可以使用Linux的重定向命令使gawk的输出送往一个文件:
gawk-fscriptfilename>save_file
BEGIN和END
有两个特殊的模式在gawk中非常有用。BEGIN模式用来指明gawk开始处理一个文件之前执行一些动作。BEGIN经常用来初始化数值,设置参数等。END模式用来在文件处理完成后执行一些指令,一般用作总结或注释。
BEGIN和END中所有要执行的指令都应该用花括号括起来。BEGIN和END必须使用大写。
请看下面的例子:
BEGIN{print"Startingtheprocessthefile"}
$1=="UNIX"{print}
$2>10{printf"Thislinehasavalueof%d",$2}
END{print"Finishedprocessingthefile.Bye!"}
此程序中,先显示一条信息:Startingtheprocessthefile,然后将所有第一个字段等于UNIX的整条记录显示出来,然后再显示第二个字段大于10的记录,最后显示信息:Finished processingthefile.Bye!。
变量
在gawk中,可以用等号(=)给一个变量赋值:
var1=10
在gawk中,你不必事先声明变量类型。
请看下面的例子:
$1=="Plastic"{count=count+1}
如果第一个字段是Plastic,则count的值加1。在此之前,我们应当给count赋予过初值,一般是在BEGIN部分。
下面是比较完整的例子:
BEGIN{count=0}
$5=="UNIX"{count=count+1}
END{printf"%doccurrencesofUNIXwerefound",count}
变量可以和字段和数值一起使用,所以,下面的表达式均为合法:
count=count+$6
count=$5-8
count=$5+var1
变量也可以是格式的一部分,例如:
$2>max_value{print"Maxvalueexceededby",$2-max_value}
$4-var1
gawk语言中有几个十分有用的内置变量,现在列于下面:
NR已经读取过的记录数。
FNR从当前文件中读出的记录数。
FILENAME输入文件的名字。
FS字段分隔符(缺省为空格)。
RS记录分隔符(缺省为换行)。
OFMT数字的输出格式(缺省为%g)。
OFS输出字段分隔符。
ORS输出记录分隔符。
NF当前记录中的字段数。
如果你只处理一个文件,则NR和FNR的值是一样的。但如果是多个文件,NR是对所有的文件来说的,而FNR则只是针对当前文件而言。
例如:
NR<=5{print"Notenoughfieldsintherecord"}
检查记录数是否小于5,如果小于5,则显示出错信息。
FS十分有用,因为FS控制输入文件的字段分隔符。例如,在BEGIN格式中,使用如下的命令:
FS=":"
控制结构
if表达式
if表达式的语法如下:
if(expression){
commands
}
else{
commands
}
例如:
#asimpleifloop
(if($1==0){
print"This cell has a value of zero"
}
else{
printf"The value is %d\n",$1
})
再看下一个例子:
#anicely form attedi floop
(if($1>$2){
print"The first column is larger"
}
else{
print"The second column is larger"
})
while循环
while循环的语法如下:
while(expression){
commands
}
例如:
#interest calculation computes compound interest
#inputs from a file arethea mount,interest_rateandyears
{var=1
while(var<=$3){
printf("%f\n",$1*(1+$2)^var)
var++
for循环
for循环的语法如下:
for(initialization;expression;increment){
command
}
例如:
#interest calculation computes compound interest
#inputs from a fil earethea mount,interest_rateandyears
{for(var=1;var<=$3;var++){
printf("%f\n",$1*(1+$2)^var)
}}
next和exit
next指令用来告诉gawk处理文件中的下一个记录,而不管现在正在做什么。语法如下:
{command1
command2
command3
next
command4
}
程序只要执行到next指令,就跳到下一个记录从头执行命令。因此,本例中,command4指令永远不会被执行。
程序遇到exit指令后,就转到程序的末尾去执行END,如果有END的话。
数组
gawk语言支持数组结构。数组不必事先初始化。声明一个数组的方法如下:
arrayname[num]=value
请看下面的例子:
#reverse lines in a file
{line[NR]=$0} #remember each line
END{var=NR #output lines in reverse order
while(var>0){
printline[var]
var--
}
此段程序读取一个文件的每一行,并用相反的顺序显示出来。我们使用NR作为数组的下标来存储文件的每一条记录,然后在从最后一条记录开始,将文件逐条地显示出来。
自定义函数
用户自定义函数
复杂的gawk程序常常可以使用自己定义的函数来简化。调用用户自定义函数与调用内部函数的方法一样。函数的定义可以放在gawk程序的任何地方。
用户自定义函数的格式如下:
functionname(parameter-list){
body-of-function
}
name是所定义的函数的名称。一个正确的函数名称可包括一序列的字母、数字、下标线(underscores),但是不可用数字做开头。parameter-list是函数的全部参数的列表,各个参数之间以逗点隔开。body-of-function包含gawk的表达式,它是函数定义里最重要的部分,它决定函数实际要做的事情。
下面这个例子,会将每个记录的第一个字段的值的平方与第二个字段的值的平方加起来。
{print"sum=",SquareSum($1,$2)}
function SquareSum(x,y){
sum=x*x+y*y
returnsum
}
几个实例
最后,再举几个gawk的例子:
gawk'{if(NF>max)max=NF}
END{printmax}'
此程序会显示所有输入行之中字段的最大个数。
gawk'length($0)>80'
此程序会显示出超过80个字符的每一行。此处只有模式被列出,动作是采用缺省值显示整个记录。
gawk'NF>0'
显示拥有至少一个字段的所有行。这是一个简单的方法,将一个文件里的所有空白行删除。
gawk'BEGIN{for(i=1;i<=7;i++)
printint(101*rand())}'
此程序会显示出范围是0到100之间的7个随机数。
ls-lfiles|gawk'{x+=$4};END{print"totalbytes:"x}'
此程序会显示出所有指定的文件的总字节数。
expandfile|gawk'{if(x
此程序会将指定文件里最长一行的长度显示出来。expand会将tab改成space,所以是用实际的右边界来做长度的比较。
gawk'BEGIN{FS=":"}
{print$1|"sort"}'/etc/passwd
此程序会将所有用户的登录名称,依照字母的顺序显示出来。
gawk'{nlines++}
END{printnlines}'
此程序会将一个文件的总行数显示出来。
gawk'END{printNR}'
此程序也会将一个文件的总行数显示出来,但是计算行数的工作由gawk来做。
gawk'{printNR,$0}'
此程序显示出文件的内容时,会在每行的最前面显示出行号,它的函数与‘cat-n’类似。