功能:
awk是行处理器: 相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,通常用来格式化文本信息。
一、命令格式:
[root@localhost ~]# awk '条件1 {动作 1} 条件 2 {动作 2} …' 文件名
二、命令说明:
- 条件:
一般为关系表达式
- 动作
格式化输出
流程控制语句
三、命令使用:
格式化输出:列出 student.txt 文件的第二个字段和第六个字段
[root@localhost ~]# awk '{printf $2 "\t" $6 "\n"}' student.txt
Name Average
Liming 87.66
Sc 85.66
Gao 91.66
没有设定任何的条件类型,所以student.txt文件中的所有内容都符合条件,动作会无条件执行。动作是格式化输出 printf,"$2"和"$6"分别代表第二个字段和第六个字段。
cut命令不能很好地识别空格作为分隔符,awk只要分隔开,不论是空格还是制表符皆可识别。
[root@localhost ~]#df -h | awk '{print $1 "\t" $3}'
文件系统 已用
/dev/sda3 1.8G
tmpfs 0
/dev/sda1 26M
/dev/sr0 3.5G
#注意:如果使用 printf 动作,就必须在最后加入"\n",因为 printf 只能识别标准输出格式;如果我们不使用"\n",它就不会换行。而 print 动作则会在每次输出后自动换行,所以不用在最后加入"\n"
四、awk的条件:
- BEGIN:awk的保留字,是一种特殊条件类型。
执行时机:在awk程序一开始,尚未读取任何数据之前
一旦BEGIN后的动作执行一次,当awk开始从文件中读入数据时,BEGIN的条件就不再成立,即BEGIN的动作只能被执行一次
[root@localhost ~]# awk 'BEGIN{printf "This is a transcript\n"}
{printf $2 "\t" $6 "\n"}' student.txt
#awk命令只要检测不到完整的单引号就不会执行,所以这条命令的换行不用加入"\",就是一行命令
#这里定义了两个动作
#第一个动作使用BEGIN条件,所以会在读入文件数据前打印"这是一张成绩单"(只会执行一次)
#第二个动作会打印文件的第二个字段和第六个字段
This is a transcript
Name Average
Liming 87.66
Sc 85.66
Gao 91.66
- END:awk的保留字,与BEGIN相反
执行时机:在awk程序处理完所有数据后执行。
END后的动作只在程序结束时执行一次。
[root@localhost ~]# awk 'END{printf "The End \n"}
{printf $2 "\t" $6 "\n"}' student.txt
#输出结尾输入"The End",这并不是文档本身的内容,而且只会执行一次
Name Average
Liming 87.66
Sc 85.66
Gao 91.66
The End
- 关系运算符
实例1:查看平均成绩大于等于87分的学员姓名
[root@localhost ~]# cat student.txt | grep -v Name |awk'$6 >= 87 {printf $2'\n"}'
#使用cat输出文件内容,用grep取反包含"Name"的行
#判断第六个字段(平均成绩)大于等于87分的行,如果判断式成立,则打印第六列(学员名)
Liming
Gao
加入条件之后,只有条件成立,动作才会执行。
实例2:查看SC用户的平均成绩
注意:在 awk 中,只有使用"//“包含的字符串,awk 命令才会査找。也就是说,字符串必须用”//"包含,awk 命令才能正确识别。
[root@localhost ~]# awk'$2 -/SC/ {printf $6 "\n"}' student.txt
#如果第二个字段中包含"Sc"字符,则打印第六个字段
85.66
- 正则表达式
如果想让awk识别字符串,则必须使用“//”包含
- 实例1:打印Liming的成绩
[root@localhost ~]# awk '/Liming/ {print}' student.txt
#打印Liming的成绩
1 Liming 82 95 86 87.66
- 实例2:当使用 df 命令査看分区的使用情况时,如果只想査看真正的系统分区的使用情况,而不想査看光盘和临时分区的使用情况
[root@localhost ~]# df -h | awk '/sda[0-9]/ {printf $1 '\t\ $5 "\n"}'
#查询包含"sda数字"的行,并打印第一个字段和第五个字段
/dev/sda3 10%
/dev/sda1 15%
五、awk的流程控制
awk编程是一门完整的程序语言,awk中允许定义变量、使用运算符、使用流程控制语句以及定义函数。
- 实例1:
查看student.txt.文件的内容
[root@localhost ~]# cat student.txt
ID Name PHP Linux MySQL Average
1 Liming 82 95 86 87.66
2 Sc 74 96 87 85.66
3 Gao 99 83 93 91.66
使用awk定义变量与调用变量的值,如统计PHP成绩的总分
[root@localhost ~]# awk'NR==2{php1 =$3}
NR==3{php2=$3}
NR==4{php3= $3;totle=php1+php2+php3;print "totle php is" totle}' student.txt
#统计PHP成绩的总分
totle php is 255
- NR2{php1=$3}:(条件是NR2,动作是php=$3)
是指如果输入数据是第二行(第一行是标题行),就把第二行的第三个字段的值赋予变量"php1"。 - NR==3{php2=$3}:是指如果输入数据是第三行,就把第三行的第三个字段的值赋予变量"php2"。
- NR4{php3=$3;totle=php1+php2+php3;print"totle php is"totle}":("NR4"是条件,后面{}中的都是动作)是指如果输入数是第四行,就把第四行的第三个字段的值赋予变量"php3";
- 然后定义变量 totle 的值是"php1+php2+php3";最后输出"totle php is"关键字,后面加变量 totle 的值。
awk编程注意事项:
- 多个条件{动作}可以用空格分隔,也可以用回车分隔。
- 在一个动作中,如果需要执行多条命令,则需要用空格分隔,或用回车分隔。
- 在awk中,变量的赋值与调用都不需要加入"$"符号。
- 在条件中判断两个值是否相同,请使用"==",以便和变量赋值进行区分。
实例2:假设 Linux 成绩大于 90 分,就非常棒
[root@localhost ~]# awk'{if (NR>=2)
{if ($4>90) printf $2" is a good man!\n"}}' student.txt
#程序中有两个if判断,第一个判断行号大于2,第二个判断Linux成绩大于90分
Liming is a good man!
Sc is a good man!
在 awk 中,if 判断语句完全可以直接利用 awk 自带的条件来取代,刚刚的脚本可以改写成这样:
[root@localhost ~]# awk' NR>=2 {test=$4}
test>90 {printf $2" is a good man!\n"}' student.txt
#先判断行号,如果大于2,就把第四个字段的值赋予变量test
#再判断成绩,如果test的值大于90分,就打印好男人
Liming is a good man!
Sc is a good man!
六、awk命令执行过程:
- 如果有BEGIN条件,则先执行BEGIN定义的动作
- 如果没有BEGIN条件,则读入第一行,把第一行的数据依次赋予$0、$1、$2等变量,其中$0代表此行的整体数据,$1代表第一个字段,$2代表第二个字段;
- 依据条件类型判断动作是否执行,如果条件符合,则执行动作,否则读入下一行数据。如果没有条件,则每行都执行动作;
- 读入下一行数据,重复执行此步骤