LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: mikkoyue

管理脚本语言 [转]

[复制链接]
 楼主| 发表于 2005-3-22 10:31:54 | 显示全部楼层
内部函数

  gawk中有各种的内部函数,现在介绍如下:

 sqrt(x)   求x的平方根
 sin(x)    求x的正弦函数
 cos(x)    求x的余弦函数
 atan2(x,y) 求x/y的余切函数
 log(x)    求x的自然对数
 exp(x)    求x的e次方
 int(x)    求x的整数部分
 rand()    求0和1之间的随机数
 srand(x)   将x设置为rand()的种子数

index(in,find)在字符串in中寻找字符串find第一次出现的地方,返回值是字符串find出现在字符串in里面的位置。如果在字符串in里面找不到字符串find,则返回值为0。
例如:printindex("peanut","an")
显示结果3。

length(string)求出string有几个字符。
例如:length("abcde")
显示结果5。

match(string,regexp)在字符串string中寻找符合regexp的最长、最靠左边的子字符串。返回值是regexp在string 的开始位置,即index值。match函数将会设置系统变量RSTART等于index的值,系统变量RLENGTH等于符合的字符个数。如果不符合,则会设置RSTART为0、RLENGTH为-1。
sprintf(format,expression1,...)和printf类似,但是sprintf并不显示,而是返回字符串。
例如:sprintf("pi=%.2f(approx.)",22/7)
返回的字符串为pi=3.14(approx.)

sub(regexp,replacement,target)在字符串target中寻找符合regexp的最长、最靠左的地方,以字串replacement代替最左边的regexp。
例如:
str="water,water,everywhere"
sub(/at/,"ith",str)
结果字符串str会变成
wither,water,everywhere

gsub(regexp,replacement,target)与前面的sub类似。在字符串target中寻找符合regexp的所有地方,以字符串replacement代替所有的regexp。
例如:str="water,water,everywhere"
gsub(/at/,"ith",str)
结果字符串str会变成
wither,wither,everywhere

substr(string,start,length)返回字符串string的子字符串,这个子字符串的长度为length,从第start个位置开始。
例如:substr("washington",5,3)返回值为ing如果没有length,则返回的子字符串是从第start个位置开始至结束。
例如:substr("washington",5)
返回值为ington。

tolower(string)将字符串string的大写字母改为小写字母。
例如:tolower("MiXeDcAsE123")
返回值为mixedcase123。

toupper(string)将字符串string的小写字母改为大写字母。
例如:toupper("MiXeDcAsE123")
返回值为MIXEDCASE123。

输入输出的内部函数
close(filename)将输入或输出的文件filename关闭。
system(command)此函数允许用户执行操作系统的指令,执行完毕后将回到gawk程序。
例如:BEGIN{system("ls")}
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-22 10:33:28 | 显示全部楼层
字符串和数字

  字符串就是一连串的字符,它可以被gawk逐字地翻译。字符串用双引号括起来。数字不能用双引号括起来,并且gawk将它当作一个数值。
例如:gawk'$1!="Tim"{print}'testfile
此命令将显示第一个字段和Tim不相同的所有记录。如果命令中Tim两边不用双引号,gawk将不能正确执行。
再如:gawk'$1=="50"{print}'testfile
此命令将显示所有第一个字段和50这个字符串相同的记录。gawk不管第一字段中的数值的大小,而只是逐字地比较。这时,字符串50和数值50并不相等。

  我们可以让动作显示一些比较复杂的结果。例如:

gawk'$1!="Tim"{print$1,$5,$6,$2}'testfile

  你也可以使用一些换码控制符格式化整行的输出。之所以叫做换码控制符,是因为gawk对这些符号有特殊的解释。下面列出常用的换码控制符:

 \a警告或响铃字符。
 \b后退一格。
 \f换页。
 \n换行。
 \r回车。
 \tTab。
 \v垂直的tab。

  在gawk中,缺省的字段分隔符一般是空格符或TAB。但你可以在命令行使用-F选项改变字符分隔符,只需在-F后面跟着你想用的分隔符即可。

gawk-F";"'/tparker/{print}'/etc/passwd

在此例中,你将字符分隔符设置成分号。注意:-F必须是大写的,而且必须在第一个引号之前。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-22 10:34:40 | 显示全部楼层
元字符

  gawk语言在格式匹配时有其特殊的规则。例如,cat能够和记录中任何位置有这三个字符的字段匹配。但有时你需要一些更为特殊的匹配。如果你想让cat只和concatenate匹配,则需要在格式两端加上空格:
/cat/{print}

再例如,你希望既和cat又和CAT匹配,则可以使用或(|):
/cat|CAT/{print}

  在gawk中,有几个字符有特殊意义。下面列出可以用在gawk格式中的这些字符:

?^表示字段的开始。
例如:
$3~/^b/
如果第三个字段以字符b开始,则匹配。

?$表示字段的结束。
例如:
$3~/b$/
如果第三个字段以字符b结束,则匹配。

?.表示和任何单字符m匹配。
例如:
$3~/i.m/
如果第三个字段有字符i,则匹配。

?|表示“或”。
例如:
/cat|CAT/
和cat或CAT字符匹配。

?*表示字符的零到多次重复。
例如:
/UNI*X/
和UNX、UNIX、UNIIX、UNIIIX等匹配。

?+表示字符的一次到多次重复。
例如:
/UNI+X/
和UNIX、UNIIX等匹配。

?\{a,b\}表示字符a次到b次之间的重复。
例如:
/UNI\{1,3\}X
和UNIX、UNIIX和UNIIIX匹配。

??表示字符零次和一次的重复。
例如:
/UNI?X/
和UNX和UNIX匹配。

?[]表示字符的范围。
例如:
/I[BDG]M/
和IBM、IDM和IGM匹配

?[^]表示不在[]中的字符。
例如:
/I[^DE]M/
和所有的以I开始、M结束的包括三个字符的字符串匹配,除了IDM和IEM之外。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-22 10:35:45 | 显示全部楼层
调用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
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-22 10:37:15 | 显示全部楼层
BEGIN和END

  有两个特殊的模式在gawk中非常有用。BEGIN模式用来指明gawk开始处理一个文件之前执行一些动作。BEGIN经常用来初始化数值,设置参数等。END模式用来在文件处理完成后执行一些指令,一般用作总结或注释。

  BEGIN和END中所有要执行的指令都应该用花括号括起来。BEGIN和END必须使用大写。
请看下面的例子:

  1. BEGIN{print"Startingtheprocessthefile"}
  2. $1=="UNIX"{print}
  3. $2>10{printf"Thislinehasavalueof%d",$2}
  4. END{print"Finishedprocessingthefile.Bye!"}
复制代码

  此程序中,先显示一条信息:Startingtheprocessthefile,然后将所有第一个字段等于UNIX的整条记录显示出来,然后再显示第二个字段大于10的记录,最后显示信息:Finished processingthefile.Bye!。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-22 10:40:32 | 显示全部楼层
变量

  在gawk中,可以用等号(=)给一个变量赋值:
var1=10
  在gawk中,你不必事先声明变量类型。

请看下面的例子:
$1=="lastic"{count=count+1}

  如果第一个字段是Plastic,则count的值加1。在此之前,我们应当给count赋予过初值,一般是在BEGIN部分。
下面是比较完整的例子:

  1. BEGIN{count=0}
  2. $5=="UNIX"{count=count+1}
  3. END{printf"%doccurrencesofUNIXwerefound",count}
复制代码

  变量可以和字段和数值一起使用,所以,下面的表达式均为合法:
count=count+$6
count=$5-8
count=$5+var1

  变量也可以是格式的一部分,例如:
$2>max_value{print"Maxvalueexceededby",$2-max_value}
$4-var1<min_value{print"Illegalvalueof",$4}

  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=":"


  
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-22 10:45:46 | 显示全部楼层
控制结构

if表达式
if表达式的语法如下:
if(expression){
 commands
} else {
 commands
}
例如:
  1. #asimpleifloop
  2. (if($1==0){
  3.   print"This cell has a value of zero"
  4. }
  5. else{
  6.   printf"The value is %d\n",$1
  7. })
复制代码

再看下一个例子:
  1. #anicely form attedi floop
  2. (if($1>$2){
  3.   print"The first column is larger"
  4. }
  5. else{
  6.   print"The second column is larger"
  7. })
复制代码


while循环
while循环的语法如下:
while(expression){
 commands
}
例如:
  1. #interest calculation computes compound interest
  2. #inputs from a file arethea mount,interest_rateandyears
  3. var=1
  4. while(var<=$3){
  5.   printf("%f\n",$1*(1+$2)^var)
  6.   var++
  7. }
复制代码


for循环
for循环的语法如下:
for(initialization;expression;increment){
 command
}
例如:
  1. #interest calculation computes compound interest
  2. #inputs from a fil earethea mount,interest_rateandyears
  3. {for(var=1;var<=$3;var++){
  4.   printf("%f\n",$1*(1+$2)^var)
  5. }}
复制代码


next和exit
next指令用来告诉gawk处理文件中的下一个记录,而不管现在正在做什么。语法如下:
{command1
 command2
 command3
 next
 command4
}
程序只要执行到next指令,就跳到下一个记录从头执行命令。因此,本例中,command4指令永远不会被执行。
程序遇到exit指令后,就转到程序的末尾去执行END,如果有END的话。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-22 10:47:13 | 显示全部楼层
数组

  gawk语言支持数组结构。数组不必事先初始化。声明一个数组的方法如下:

arrayname[num]=value

请看下面的例子:

  1. #reverse lines in a file
  2. {line[NR]=$0} #remember each line
  3. END{var=NR #output lines in reverse order
  4. while(var>0){
  5.   printline[var]
  6.   var--
  7. }
复制代码

  此段程序读取一个文件的每一行,并用相反的顺序显示出来。我们使用NR作为数组的下标来存储文件的每一条记录,然后在从最后一条记录开始,将文件逐条地显示出来。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-22 10:48:28 | 显示全部楼层
自定义函数

用户自定义函数

  复杂的gawk程序常常可以使用自己定义的函数来简化。调用用户自定义函数与调用内部函数的方法一样。函数的定义可以放在gawk程序的任何地方。
用户自定义函数的格式如下:
functionname(parameter-list){
  body-of-function
}
  name是所定义的函数的名称。一个正确的函数名称可包括一序列的字母、数字、下标线(underscores),但是不可用数字做开头。 parameter-list是函数的全部参数的列表,各个参数之间以逗点隔开。body-of-function包含gawk的表达式,它是函数定义里最重要的部分,它决定函数实际要做的事情。

  下面这个例子,会将每个记录的第一个字段的值的平方与第二个字段的值的平方加起来。

  1. {print"sum=",SquareSum($1,$2)}
  2. function SquareSum(x,y){
  3.   sum=x*x+y*y
  4.   returnsum
  5. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-22 10:50:00 | 显示全部楼层
几个实例

最后,再举几个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<length())x=length()}
END{print"maximumlinelengthis"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’类似。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表