小女巫 发表于 2015-1-14 20:18:53

来一发CentOS Shell经常使用技能 awk编程

如果您觉得本篇CentOSLinux教程讲得好,请记得点击右边漂浮的分享程序,把好文章分享给你的小伙伴们!awk编程:

1.变量:
在awk中变量不必界说便可利用,变量在赋值时即已完成了界说。变量的范例能够是数字、字符串。依据利用的分歧,未初始化变量的值为0或空缺字符串"",这次要取决于变量使用的高低文。上面为变量的赋值负号列表:
标记寄义等价情势=a=5a=5+=a=a+5a+=5-=a=a-5a-=5*=a=a*5a*=5/=a=a/5a/=5%=a=a%5a%=5^=a=a^5a^=5/>awk$1~/Tom/{Wage=$2*$3;printWage}filename
该下令将从文件中读取,并查找第一个域字段婚配Tom的纪录,再将其第二和第三个字段的乘积赋值给自界说的Wage变量,最初经由过程print下令将该变量打印输入。

/>awk{$5=1000*$3/$2;print}filename
在下面的下令中,假如$5不存在,awk将盘算表达式1000*$3/$2的值,并将其赋值给$5。假如第五个域存在,则用表达式掩盖$5本来的值。

我们一样也能够在下令行中界说自界说的变量,用法以下:
/>awk-F:-fawkscriptmonth=4year=2011filename
这里的month和year都是自界说变量,且分离被赋值为4和2000,在awk的剧本中这些变量将能够被间接利用,他们和剧本中界说的变量在利用上没有任何区分。

除此以外,awk还供应了一组内建变量(变量名全体年夜写),见以下列表:
变量名变量内容ARGC下令行参数的数目。ARGIND下令行正在处置确当前文件的AGV的索引。ARGV下令行参数数组。CONVFMT转换数字格局。ENVIRON从shell中传送来的包括以后情况变量的数组。ERRNO当利用close函数大概经由过程getline函数读取的时分,产生的从头定向毛病的形貌信息就保留在这个变量中。FIELDWIDTHS在对纪录举行流动域宽的支解时,能够替换FS的分开符的列表。FILENAME以后的输出文件名。FNR以后文件的纪录号。FS输出分开符,默许是空格。IGNORECASE在正则表达式和字符串操纵中封闭巨细写敏感。NF以后文件域的数目。NR以后文件纪录数。OFMT数字输入格局。OFS输入域分开符。ORS输入纪录分开符。RLENGTH经由过程match函数婚配的字符串的长度。RS输出纪录分开符。RSTART经由过程match函数婚配的字符串的偏移量。SUBSEP下标分开符。/>catemployees2
TomJones:4424:5/12/66:543354
MaryAdams:5346:11/4/63:28765
SallyChang:1654:7/22/54:650000
MaryBlack:1683:9/23/44:336500

/>awk-F:{IGNORECASE=1};$1=="maryadams"{printNR,$1,$2,$NF}employees2
2MaryAdams534628765
/>awk-F:$1=="maryadams"{printNR,$1,$2,$NF}employees2
没有输入了局。
当IGNORECASE内置变量的值为非0时,暗示在举行字符串操纵和处置正则表达式时封闭巨细写敏感。这里的"maryadams"将婚配文件中的"MaryAdmams"纪录。最初print打印出第1、第二和最初一个域。必要申明的是NF暗示以后纪录域的数目,因而$NF将暗示最初一个域的值。

awk在举措局部还供应了BEGIN块和END块。个中BEGIN举措块在awk处置任何输出文件行之前实行。现实上,BEGIN块能够在没有任何输出文件的前提下测试。由于在BEGIN块实行终了之前awk将不读取任何输出文件。BEGIN块一般被用来改动内建变量的值,如OFS、RS或FS等。也可以用于初始化自界说变量值,或打印输入题目。
/>awkBEGIN{FS=":";OFS="        ";ORS="

"}{print$1,$2,$3}filename
上例中awk在处置文件之前,已将域分开符(FS)设置为冒号,输入文件域分开符(OFS)设置为制表符,输入纪录分开符(ORS)被设置为两个换行符。BEGIN以后的举措模块中假如有多个语句,他们之间用分号分开。
和BEGIN恰好相反,END模块中的举措是在全部文件处置终了以后被实行的。
/>awkEND{print"Thenumberoftherecordsis"NR}filename
awk在处置输出文件以后,实行END模块中的举措,上例中NR的值是读进的最初一个纪录的纪录号。

/>awk/Mary/{count++}END{print"Marywasfound"count"times."}employees2
Marywasfound2times.
/>awk/Mary/{count++}END{print"Marywasfound"count"times."}employees2
Marywasfound2times.

/>cattestfile
northwestNWCharlesMain3.0.98334
westernWESharonGray5.3.97523
southwestSWLewisDalsass2.7.8218
southernSOSuanChin5.1.95415
southeastSEPatriciaHemenway4.0.7417
easternEATBSavage4.4.84520
northeastNEAMMainJr.5.1.94313
northNOMargotWeber4.5.8959
centralCTAnnStephens5.7.94513

/>awk/^north/{count+=1;printcount}testfile#如纪录以正则north开首,则创立变量count同时增一,再输入其值。
1
2
3

#这里只是输入前三个字段,个中第七个域先被赋值给变量x,在自减一,最初再同时打印出他们。
/>awkNR<=3{x=$7--;print"x="x",$7="$7}testfile
x=3,$7=2
x=5,$7=4
x=2,$7=1

#打印NR(纪录号)的值在2--5之间的纪录。
/>awkNR==2,NR==5{print"Therecordnumberis"NR}testfile
Therecordnumberis2
Therecordnumberis3
Therecordnumberis4
Therecordnumberis5

#打印情况变量USER和HOME的值。情况变量的值由父历程shell传送给awk步伐的。
/>awkBEGIN{printENVIRON["USER"],ENVIRON["HOME"]}
root/root

#BEGIN块儿中对OFS内置变量从头赋值了,因而前面的输入域分开符改成了        。
/>awkBEGIN{OFS="        "};/^Sharon/{print$1,$2,$7}testfile
westernWE5

#从输出文件中找到以north开首的纪录count就加一,最初在END块中输入该变量。
/>awk/^north/{count++};END{printcount}testfile
3
2.从头定向:
在举措语句中利用shell通用的重定向输入标记">"就能够完成awk的重定向操纵,当利用>的时分,原有文件将被清空,同时文件延续翻开,直到文件被明白的封闭大概awk步伐停止。来自前面的打印语句的输入会追加到后面内容的前面。标记">>"用来翻开一个文件可是不清空原有文件的内容,重定向的输入只是被追加到这个文件的开端。
/>awk$4>=70{print$1,$2>"passing_file"}filename#注重这里的文件名必要用双引号括起来。
#经由过程两次cat的了局能够看出>和>>的区分。
/>awk/north/{print$1,$3,$4>"districts"}testfile
/>catdistricts
northwestJoelCraig
northeastTJNichols
northValShultz
/>awk/south/{print$1,$3,$4>>"districts"}testfile
/>catdistricts
northwestJoelCraig
northeastTJNichols
northValShultz
southwestChrisFoster
southernMayChin
southeastDerekJonhson

awk中关于输出重定向是经由过程getline函数来完成的。getline函数的感化是从尺度输出、管道大概以后正在处置的文件以外的其他输出文件取得输出。他卖力从输出取得下一行的内容,并给NF、NR和FNR等外建变量赋值。假如失掉一个纪录,getline就前往1,假如到达文件开端就前往0。如果呈现毛病,如翻开文件失利,就前往-1。
/>awkBEGIN{"date"|getlined;printd}
TueNov1515:31:42CST2011
上例中的BEGIN举措模块中,先实行shell下令date,并经由过程管道输入给getline,然后再把输入赋值给自界说变量d并打印输入它。

/>awkBEGIN{"date"|getlined;split(d,mon);printmon}
Nov
上例中date下令经由过程管道输入给getline并赋值给d变量,再经由过程内置函数split将d拆分为mon数组,最初print出mon数组的第二个元素。

/>awkBEGIN{while("ls"|getline)print}
employees
employees2
testfile
下令ls的输入传送给getline作为输出,轮回的每一个重复,getline都从ls的了局中读取一行输出,并把他打印到屏幕。

/>awkBEGIN{printf"Whatisyourname?";
getlinename<"/dev/tty"}
$1~name{print"Found"name"online",NR"."}
END{print"Seeya,"name"."}employees2
Whatisyourname?Mary
FoundMaryonline2.
Seeya,Mary.
上例先是打印出BEGIN块中的"Whatisyourname?",然后守候用户从/dev/tty输出,并将读进的数据赋值给name变量,以后再从输出文件中读取纪录,并找到婚配输出变量的纪录并打印出来,最初在END块中输入开头信息。

/>awkBEGIN{while(getline<"/etc/passwd">0)lc++;printlc}
32
awk将逐行读取/etc/passwd文件中的内容,在到达文件开端之前,计数器lc一向自增1,当到了开端后打印lc的值。lc的值为/etc/passwd文件的行数。
因为awk中同时翻开的管道只要一个,那末在翻开下一个管道之前必需封闭它,管道标记右侧能够经由过程能够经由过程双引号封闭管道。假如不封闭,它将一直坚持翻开形态,直到awk加入。
/>awk{print$1,$2,$3|"sort-4+1-2+0-1"}END{close("sort-4+1-2+0-1")}filename
上例中END模块中的close显现封闭了sort的管道,必要注重的是close中封闭的下令必需和现在翻开时的完整婚配,不然END模块发生的输入会和之前的输入一同被sort分类。

3.前提语句:
awk中的前提语句是从C言语中自创来的,见以下声明体例:
if(expression){
statement;
statement;
......
}
/>awk{if($6>50)print$1"Toohign"}filename
/>awk{if($6>20&&$6<=50){safe++;print"OK}}filename

if(expression){
statement;
}else{
statement2;
}
/>awk{if($6>50)print$1"Toohigh";elseprint"RangeisOK"}filename
/>awk{if($6>50){count++;print$3}else{x=5;print$5}filename

if(expression){
statement1;
}elseif(expression1){
statement2;
}else{
statement3;
}
/>awk{if($6>50)print"$6>50"elseif($6>30)print"$6>30"elseprint"other"}filename

4.轮回语句:
awk中的轮回语句一样自创于C言语,撑持while、do/while、for、break、continue,这些关头字的语义和C言语中的语义完整不异。

5.流程把持语句:
next语句是从文件中读取下一行,然后重新入手下手实行awk剧本。
exit语句用于停止awk步伐。它停止对纪录的处置。可是不会略过END模块,假如exit()语句被赋值0--255之间的参数,如exit(1),这个参数就被打印到下令行,以判别加入乐成仍是失利。

6.数组:
因为awk中数组的下标能够是数字和字母,数组的下标一般被称为关头字(key)。值和关头字都存储在外部的一张针对key/value使用hash的表格里。因为hash不是按次存储,因而在显现数组内容时会发明,它们并非依照你意料的按次显现出来的。数组和变量一样,都是在利用时主动创立的,awk也一样会主动判别其存储的是数字仍是字符串。一样平常而言,awk中的数组用来从纪录中搜集信息,能够用于盘算总和、统计单词和跟踪模板被婚配的次数等等。
/>catemployees
TomJones44245/12/66543354
MaryAdams534611/4/6328765
SallyChang16547/22/54650000
BillyBlack16839/23/44336500

/>awk{name=$2};END{for(i=0;i<NR;i++)printi,name}employees
0Jones
1Adams
2Chang
3Black
在上例中,数组name的下标是变量x。awk初始化该变量的值为0,在每次利用后自增1,读取文件中的第二个域的值被顺次赋值给name数组的各个元素。在END模块中,for轮回遍历数组的值。由于下标是关头字,以是它纷歧定从0入手下手,能够从任何值入手下手。

#这里是用内置变量NR作为数组的下标了。
/>awk{id=$3};END{for(x=1;x<=NR;x++)printid}employees
4424
5346
1654
1683

awk中还供应了一种specialfor的轮回,见以下声明:
for(iteminarrayname){
printarrayname
}

/>catdb
TomJones
MaryAdams
SallyChang
BillyBlack
TomSavage
TomChung
ReggieSteel
TommyTucker

/>awk/^Tom/{name=$1};END{for(i=1;i<=NR;i++)printname}db
Tom



Tom
Tom

Tommy
从输入了局能够看出,只要婚配正则表达式的纪录的第一个域被赋值给数组name的指定下标元素。由于用NR作为下标,以是数组的下标不成能是一连的,因此在END模块顶用传统的for轮回打印时,不存在的元素就打印空字符串了。上面我们看看用specialfor的体例会有甚么样的输入。
/>awk/^Tom/{name=$1};END{for(iinname)printname}db
Tom
Tom
Tommy
Tom

上面我们看一下用字符串作为下标的例子:(假如下标是字符串笔墨常量,则必要用双引号括起来)
/>cattestfile2
tom
mary
sean
tom
mary
mary
bob
mary
alex
/>awk/tom/{count["tom"]++};/mary/{count["mary"]++};END{print"Thereare"count["tom"]
"Tomsand"count["mary"]"Marysinthefile."}testfile2
Thereare2Tomsand4Marysinthefile.
在上例中,count数组有两个元素,下标分离为tom和mary,每个元素的初始值都是0,没有tom被婚配的时分,count["tom"]就会加一,count["mary"]在婚配mary的时分也一样云云。END模块中打印出存储在数组中的各个元素。

/>awk{count[$1]++};END{for(nameincount)printf"%-5s%d
",name,count}testfile2
mary4
tom2
alex1
bob1
sean1
在上例中,awk是以纪录的域作为数组count的下标。

/>awk{count[$1]++;if(count[$1]>1)name[$1]++};END{print"Theduplicateswere";for(iinname)printi}testfile2
Theduplicateswere
mary
tom
在上例中,如count[$1]的元素值年夜于1的时分,也就是当名字呈现屡次的时分,一个新的数组name将被初始化,最初打印出那末数组中反复呈现的名字下标。

之前我们先容的都是怎样给数组增加新的元素,并付与初值,如今我们必要先容一下怎样删除数组中已存在的元素。要完成这一功效我们必要利用内置函数delete,见以下下令:
/>awk{count[$1]++};
END{for(nameincount){
if(count==1)
deletecount;
}
for(nameincount)
printname}testfile2
mary
tom
上例中的次要技能来自END模块,先是变量count数组,假如数组中某个元素的值即是1,则删除该元素,如许同等于删除只呈现一次的名字。最初用specialfor轮回打印出数组中仍旧存在的元素下标称号。

最初我们来看一下怎样利用下令行参数数组,见以下下令:
/>awkBEGIN{for(i=0;i<ARGC;i++)printf("argv[%d]is%s.
",i,ARGV);printf("Thenumberofarguments,ARGC=%d
",ARGC)}testfile"PeterPan"12
argvisawk.
argvistestfile.
argvisPeterPan.
argvis12.
Thenumberofarguments,ARGC=4
从输入了局能够看出,下令行参数数组ARGV是以0作为肇端下标的,下令行的第一个参数为下令自己(awk),这个利用体例和C语句main函数完整分歧。

/>awkBEGIN{name=ARGV;print"ARGVis"ARGV};$1~name{print$0}testfile2"bob"
ARGVisbob
bob
awk:(FILENAME=testfile2FNR=9)fatal:cannotopenfile`bobforreading(Nosuchfileordirectory)
先注释一下以上下令的寄义,name变量被赋值为下令行的第三个参数,即bob,以后再在输出文件中找到婚配该变量值的纪录,并打印出该纪录。
在输入的第二行报出了awk的处置毛病信息,这次要是由于awk将bob视为输出文件来处置了,但是现实上这个文件其实不存在,上面我们必要做进一步的处置来修改这个成绩。
/>awkBEGIN{name=ARGV;print"ARGVis"ARGV;deleteARGV};$1~name{print$0}testfile2"bob"
ARGVisbob
bob
从输入了局中我们能够看到我们失掉了我们想要的了局。必要注重的是delete函数的挪用需要要在BEGIN模块中完成,由于这时候awk还没有入手下手读取下令行参数中指定的文件。

7.内建函数:
字符串函数
sub(regularexpression,substitutionstring);
sub(regularexpression,substitutionstring,targetstring);

/>awk{sub("Tom","Tommy");print}employees#这里利用Tommy交换了Tom。
TommyJones44245/12/66543354

#当正则表达式Tom在第一个域中第一次被婚配后,他将被字符串"Tommy"交换,假如将sub函数的第三个参数改成$2,将不会有交换产生。
/>awk{sub("Tom","Tommy",$1);print}employees
TommyJones44245/12/66543354

gsub(regularexpression,substitutionstring);
gsub(regularexpression,substitutionstring,targetstring);
和sub分歧的是,假如第一个参数中正则表达式在纪录中呈现屡次,那末gsub将完成屡次交换,而sub只是交换第一次呈现的。

index(string,substring)
该函数将前往第二个参数在第一个参数中呈现的地位,偏移量从1入手下手。
/>awkBEGIN{printindex("hello","el")}
2

length(string)
该函数前往字符串的长度。
/>awkBEGIN{printlength("hello")}
5

substr(string,startingposition)
substr(string,startingposition,lengthofstring)
该函数前往第一个参数的子字符串,其截取肇端地位为第二个参数(偏移量为1),截取长度为第三个参数,假如没有该参数,则从第二个参数指定的地位起,直到string的开端。
/>awkBEGIN{name=substr("HelloWorld",2,3);printname}
ell

match(string,regularexpression)
该函数前往在字符串中正则表达式地位的索引,假如找不到指定的正则表达式就前往0.match函数设置内置变量RSTART为字符串中子字符串的入手下手地位,RLENGTH为到字字符串开端的字符个数。
/>awkBEGIN{start=match("GoodoleCHINA",/+$/);printstart}
10
上例中的正则表达式+$暗示在字符串的开端搜刮一连的年夜写字母。在字符串"GoodoleCHINA"的第10个地位找到字符串"CHINA"。

/>awkBEGIN{start=match("GoodoleCHINA",/+$/);printRSTART,RLENGTH}
105
RSTART暗示婚配时的肇端索引,RLENGTH暗示婚配的长度。

/>awkBEGIN{string="GoodoleCHINA";start=match(string,/+$/);printsubstr(string,RSTART,RLENGTH)}
CHINA
这里将match、RSTART、RLENGTH和substr奇妙的分离起来了。

toupper(string)
tolower(string)
以上两个函数分离前往参数字符串的年夜写和小写的情势。
/>awkBEGIN{printtoupper("hello");printtolower("WORLD")}
HELLO
world

split(string,array,fieldseperator)
split(string,array)
该函数利用作为第三个参数的域分开符把字符串分开为一个数组。假如第三个参数没有供应,则利用以后默许的FS值。
/>awkBEGIN{split("11/20/2011",date,"/");printdate}
20

variable=sprintf("stringwithformatspecifiers",expr1,expr2,...)
该函数和printf的不同同等于C言语中printf和sprintf的不同。前者将格局化后的了局输入到输入流,尔后者输入到函数的前往值中。
/>awkBEGIN{line=sprintf("%-15s%6.2f","hello",4.2);printline}
hello4.20

工夫函数:
systime()
该函数前往以后工夫间隔1970年1月1日之间相差的秒数。
/>awkBEGIN{printsystime()}
1321369554

strftime()
工夫格局化函数,其格局化划定规矩同等于C言语中的strftime函数供应的划定规矩,见以以下表:
数据格局寄义%aAbbreviatedweekdayname%AFullweekdayname%bAbbreviatedmonthname%BFullmonthname%cDateandtimerepresentationappropriateforlocale%dDayofmonthasdecimalnumber(01C31)%HHourin24-hourformat(00C23)%IHourin12-hourformat(01C12)%jDayofyearasdecimalnumber(001C366)%mMonthasdecimalnumber(01C12)%MMinuteasdecimalnumber(00C59)%pCurrentlocalesA.M./P.M.indicatorfor12-hourclock%SSecondasdecimalnumber(00C59)%UWeekofyearasdecimalnumber,withSundayasfirstdayofweek(00C53)%wWeekdayasdecimalnumber(0C6;Sundayis0)%WWeekofyearasdecimalnumber,withMondayasfirstdayofweek(00C53)%xDaterepresentationforcurrentlocale%XTimerepresentationforcurrentlocale%yYearwithoutcentury,asdecimalnumber(00C99)%YYearwithcentury,asdecimalnumber/>awkBEGIN{printstrftime("%D",systime())}
11/15/11
/>awkBEGIN{now=strftime("%T");printnow}
23:17:29

内置数学函数:
称号前往值atan2(x,y)y,x局限内的余切cos(x)余弦函数exp(x)求幂int(x)取整log(x)天然对数sin(x)正弦函数sqrt(x)平方根/>awkBEGIN{print31/3}
10.3333
/>awkBEGIN{printint(31/3)}
10

自界说函数:
自界说函数能够放在awk剧本的任何能够安排模板和举措的中央。
functionname(parameter1,parameter2,...){
statements
returnexpression
}
给函数中当地变量传送值。只利用变量的拷贝。数组经由过程地点大概指针传送,以是能够在函数外部间接改动数组元素的值。函数外部利用的任何没有作为参数传送的变量都被看作是全局变量,也就是这些变量关于全部步伐都是可见的。假如变量在函数中产生了变更,那末就是在全部步伐中产生了改动。独一向函数供应当地变量的举措就是把他们放在参数列表中,这些参数一般被放在列表的最初。假如函数挪用没有供应正式的参数,那末参数就初始化为空。return语句一般就前往步伐把持并向挪用者前往一个值。
/>catgrades
2010
3020
4030

/>catadd.sc
functionadd(first,second){
returnfirst+second
}
{printadd($1,$2)}

/>awk-fadd.scgrades
30
50
70


如果您觉得本篇CentOSLinux教程讲得好,请记得点击右边漂浮的分享程序,把好文章分享给你的好朋友们!

老尸 发表于 2015-1-15 22:52:50

来一发CentOS Shell经常使用技能 awk编程

就这样,我们一边上OS理论课,一边上这个实验,这样挺互补的,老师讲课,一步一步地布置任务

若相依 发表于 2015-1-20 20:52:03

永中office 2004增强版安装只需要默认安装即可使用并操作大多与win系统雷同,打印机的配置和管理,记录光盘等。

再见西城 发表于 2015-1-30 05:41:42

不同于Windows?系统需要花钱购买,因为Linux的核心是免费的,自由使用的,核心源代码是开放的。

飘飘悠悠 发表于 2015-2-6 10:00:15

应对Linux的发展历史和特点有所了解,Linux是抢占式多任务多用户操作系统,Linux最大的优点在于其作为服务器的强大功能,同时支持多种应用程序及开发工具。

小女巫 发表于 2015-2-15 23:50:39

为什么要学Linux呢?每个人都有不同的看法,下面我说说自己的感想吧。?

柔情似水 发表于 2015-3-4 21:37:08

把这个问题放在其他Linux社区请求帮助也是一种选择。如果Linux得不到答案,请不要以为我们觉得无法帮助你。有时只是看到你问题的人不知道答案罢了。这时换一个社区是不错的选择。

愤怒的大鸟 发表于 2015-3-11 21:26:35

硬盘安装及光盘安装,清楚了解安装Linux应注意的有关问题,如安装Linux应在最后一个分区内,至少分二个分区。

再现理想 发表于 2015-3-30 01:50:08

用户下达的命令解释给系统去执行,并将系统传回的信息再次解释给用户,估shell也称为命令解释器,有关命令的学习可参考论坛相关文章,精通英文也是学习Linux的关键。
页: [1]
查看完整版本: 来一发CentOS Shell经常使用技能 awk编程