一、概念
awk是一个报告生成器,拥有强大的文本格式化能力。
数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出;
依次对每一行进行处理,然后输出;
它在命令行中使用,但更多是作为脚本来使用。
grep、sed、awk被称为Linux三剑客:
grep适合单纯的查找或匹配文本;
sed适合编辑匹配到的文本;
awk适合格式化文本;
二、awk命令格式
awk [options] 'pattern{action}' file options参数有三个:-F指定分隔符,-f调用脚本,-v定义变量 var=value '' 引用代码块; pattern表示待匹配的模式; {action}表示一系列的动作命令; file表示等待操作的数据文件;
三、内置变量
1、分隔符
FS : 输入字段分隔符(默认是任何空格)。
[root@PCS101 ~]# cat test abc#123#dfhj#kfjda#kjd def#456#kjs#4sf#kks#09j [root@PCS101 ~]# awk '{print $1,$2}' test abc#123#dfhj#kfjda#kjd def#456#kjs#4sf#kks#09j [root@PCS101 ~]# awk -F# '{print $1,$2}' test abc 123 def 456 [root@PCS101 ~]# awk -v FS='#' '{print $1,$2}' test abc 123 def 456
OFS : 输出字段分隔符(默认值是一个空格)。
[root@PCS101 ~]# awk -v FS='#' -v OFS='------' '{print $1,$2}' test abc------123 def------456 [root@PCS101 ~]# awk -v FS='#' -v OFS='------' '{print $1 $2}' test abc123 def456
2、NR和FNR
NR : 表示记录数,在执行过程中对应于当前的行号
FNR : 同NR ,但相对于当前文件,多文件记录不递增,每个文件都从1开始。
[root@PCS101 ~]# cat t1.txt t2.txt abc def hij klm 456 789 j2k tb3 kkk djk zlm enjl fas 2d3 98s y67s 98sm [root@PCS101 ~]# awk '{print NR,$0}' t1.txt t2.txt 1 abc def hij klm 2 456 789 j2k tb3 3 kkk djk zlm enjl 4 fas 2d3 98s y67s 98sm [root@PCS101 ~]# awk '{print FNR,$0}' t1.txt t2.txt 1 abc def hij klm 2 456 789 j2k tb3 1 kkk djk zlm enjl 2 fas 2d3 98s y67s 98sm
3、RS和ORS
RS : 输入行分隔符, 默认为换行符
[root@PCS101 ~]# awk -v RS=' ' '{print NR,$0}' t1.txt 1 abc 2 def 3 hij 4 klm 456 5 789 6 j2k 7 tb3 [root@PCS101 ~]#
ORS : 输出行分隔符,默认值是一个换行符
[root@PCS101 ~]# awk -v ORS='+++' '{print NR,$0}' t1.txt 1 abc def hij klm+++2 456 789 j2k tb3+++[root@PCS101 ~]#
4、FILENAME
FILENAME : 当前输入文件的名。
[root@PCS101 ~]# awk '{print FILENAME,NR,$0}' t1.txt t2.txt t1.txt 1 abc def hij klm t1.txt 2 456 789 j2k tb3 t2.txt 3 kkk djk zlm enjl t2.txt 4 fas 2d3 98s y67s 98sm [root@PCS101 ~]#
5、ARGC和ARGV
ARGC : 命令行参数的数目。
ARGV : 包含命令行参数的数组。
[root@PCS101 ~]# awk 'BEGIN{print "aaa",ARGV[0],ARGV[1],ARGV[2],ARGC}' t1.txt t2.txt aaa awk t1.txt t2.txt 3
注意:ARGV[0]指不是'pattern{action}'
6、自定义变量
变量名区分大小写。
方式一:
[root@PCS101 ~]# awk -v myVar='testVar' 'BEGIN{print myVar}' testVar [root@PCS101 ~]# abc=666666 [root@PCS101 ~]# awk -v newVar=$abc 'BEGIN{print newVar}' 666666
方式二:
[root@PCS101 ~]# awk 'BEGIN{myvar=111;myvar2="222";print myvar,myvar2}' 111 222
其他内置变量:
$n: 当前记录的第n个字段,比如n为1表示第一个字段,n为2表示第二个字段。 $0 : 这个变量包含执行过程中当前行的文本内容。
ARGIND : 命令行中当前文件的位置(从0开始算)。
CONVFMT : 数字转换格式(默认值为%.6g)。
ENVIRON : 环境变量关联数组。
ERRNO : 最后一个系统错误的描述。
FIELDWIDTHS : 字段宽度列表(用空格键分隔)。
IGNORECASE : 如果为真,则进行忽略大小写的匹配。
NF : 表示字段数,在执行过程中对应于当前的字段数。 print $NF对应一行中最后一个字段
OFMT : 数字的输出格式(默认值是%.6g)。
RSTART : 由match函数所匹配的字符串的第一个位置。
RLENGTH : 由match函数所匹配的字符串的长度。
SUBSEP : 数组下标分隔符(默认值是34)。
print 是awk打印指定内容的主要命令,printf格式化输出命令。
其他相关:
制表符
换行符
~ 匹配,与==相比不是精确比较
!~ 不匹配,不精确比较
+ 匹配时表示1个或1个以上
/[0-9][0-9]+/ 两个或两个以上数字
/[0-9][0-9]*/ 一个或一个以上数字
-F'[:#/]' 定义三个分隔符
四、格式化输出
使用格式化输出命令printf,默认不输出换行符。
[root@PCS101 ~]# awk -F# '{printf "第一列:%s 第二列:%s " ,$1,$2}' test 第一列:abc 第二列:123 第一列:def 第二列:456
五、匹配
就是在进行命令操作之前做的条件匹配,只有符合条件的行才被操作。
1、BEGIN模式和END模式
2、关系表达式模式
可与逻辑运算符 (||, &&)一起使用
[root@PCS101 ~]# awk 'NR==1 {print $0}' test abc#123#dfhj#kfjda#kjd
3、正则模式
awk '/正则表达式/{...}' file
#查找以mysql开头的记录
[root@PCS101 ~]# awk '/^mysql/{print $0}' /etc/passwd mysql:x:1002:1002::/home/mysql:/bin/bash
4、行范围模式
awk '/正则1/,/正则2/{...}' file
从被正则1匹配的行开始到被正则2匹配的行结束,之间的所有行都会被执行后面的操作。
六、动作
所有动作的最外侧都必须有{}包裹起来。
1、算术运算:(+,-,*,/,&,!,……,++,–)
所有用作算术运算符进行操作时,操作数自动转为数值,所有非数值都变为0
2、赋值运算:(=, +=, -=,*=,/=,%=,……=,**=)
3、逻辑运算: (||, &&,!)
4、关系运算:(<, <=, >,>=,!=, ==)
5、正则运算:(~,~!)(匹配正则表达式,与不匹配正则表达式)
6、三元运算:A ? B : C
7、流程控制
(1)条件分支控制
[root@PCS101 ~]# awk '{if(NR==1) {print NR,NF}else if(NR==2){print NR,NF}}' test 1 1 2 1
(2)循环控制
#for循环语法格式1 for(初始化; 布尔表达式; 更新) { //代码语句 } [root@PCS101 ~]# awk 'BEGIN{for(i=1;i<=3;i++){print i}}' 1 2 3 #for循环语法格式2 for(变量 in 数组) { //代码语句 } #while循环语法 while( 布尔表达式 ) { //代码语句 } [root@PCS101 ~]# awk -v i=1 'BEGIN{while(i<=5){print i;i++}}' 1 2 3 4 5 #do...while循环语法 do { //代码语句 }while(条件) [root@PCS101 ~]# awk 'BEGIN{i=1;do{print i;i++}while(i<5)}' 1 2 3 4
continue:结束本次循环;
break:中断循环;
exit:不再执行动作,也不是退出awk,而是转向执行END;
[root@PCS101 ~]# awk 'BEGIN{print 1;exit;print 2;}{print "middle"}END{print "end"}' 1 end
next:结束对当前行的处理,转而处理下一行
[root@PCS101 ~]# cat t1.txt abc def hij klm 456 789 j2k tb3 [root@PCS101 ~]# awk '{if(NR==2){next};print $0}' t1.txt abc def hij klm
七、数组
数组是一个包含一系列元素的表.
#将a定义为循环中的取值列表。从数组中取出的是数组的所有元素的下标
[root@PCS101 ~]# awk 'BEGIN{a[0]="xiaohong";a[1]="xiaolan";for (i in a)print i;}' 0 1 [root@PCS101 ~]#
八、内置函数
1、算数函数
#rand是随机数函数,单独使用生成的值不变,需要配合srand使用,int截取整数部分 [root@PCS101 ~]# awk 'BEGIN{print rand()}' 0.237788 [root@PCS101 ~]# awk 'BEGIN{print rand()}' 0.237788 [root@PCS101 ~]# awk 'BEGIN{srand();print rand()}' 0.0534209 [root@PCS101 ~]# awk 'BEGIN{srand();print rand()}' 0.0632856 [root@PCS101 ~]# awk 'BEGIN{srand();print int(100*rand())}' 99
2、字符串函数
gsub sub 字符串替换函数
index返回字符串出现的位置
spilt切割
3、其他函数
asort()排序函数
九、实际应用
(1)计算/home目录下,普通文件的大小,使用KB作为单位 [root@PCS101 ~]# ls -l|awk 'BEGIN{sum=0} !/^d/{sum+=$5} END{print "total size is:",int(sum/1024),"KB"}' total size is: 4450 KB (2)统计netstat -anp 状态为LISTEN和CONNECT的连接数量分别是多少 [root@PCS101 ~]# netstat -anp|awk '$6~/LISTEN|CONNECTED/{sum[$6]++} END{for (i in sum) printf "%-10s %-6s %-3s ", i," ",sum[i]}' LISTEN 12 CONNECTED 131 (3)统计/home/cluster目录下不同用户的普通文件的总数是多少? [root@PCS101 cluster]# ls -l|awk 'NR!=1 && !/^d/{sum[$3]++} END{for (i in sum) printf "%-6s %-5s %-3s ",i," ",sum[i]}' cluster 4 root 2 统计/home/cluster目录下不同用户的普通文件的大小总size是多少? [root@PCS101 cluster]# ls -l|awk 'NR!=1 && !/^d/{sum[$3]+=$5} END{for (i in sum) printf "%-6s %-5s %-3s %-2s ",i," ",sum[i]/1024/1024,"MB"}' cluster 111.849 MB root 180.886 MB (4)输出成绩表 [root@PCS101 ~]# cat test0 Marry 2143 78 84 77 Jack 2321 66 78 45 Tom 2122 48 77 71 Mike 2537 87 97 95 Bob 2415 40 57 62 [root@PCS101 ~]# awk 'BEGIN{math=0;eng=0;com=0;printf "Lineno. Name No. Math English Computer Total ";printf "------------------------------------------------------------ "}{math+=$3; eng+=$4; com+=$5;printf "%-8s %-7s %-7s %-7s %-9s %-10s %-7s ",NR,$1,$2,$3,$4,$5,$3+$4+$5} END{printf "------------------------------------------------------------ ";printf "%-24s %-7s %-9s %-20s ","Total:",math,eng,com;printf "%-24s %-7s %-9s %-20s ","Avg:",math/NR,eng/NR,com/NR}' test0 Lineno. Name No. Math English Computer Total ------------------------------------------------------------ 1 Marry 2143 78 84 77 239 2 Jack 2321 66 78 45 189 3 Tom 2122 48 77 71 196 4 Mike 2537 87 97 95 279 5 Bob 2415 40 57 62 159 ------------------------------------------------------------ Total: 319 393 350 Avg: 63.8 78.6 70 0