1 语法

awk '条件1{动作1} 条件2{动作2}...'文件名

条件(Pattern):一般使用关系表达式作为条件--x > 10判断变量x是否大于10     
动作(Action):格式化输出流程 --控制语句

1.1条件 

1.1.1BEGIN与AFTER

[root@localhost ~]# awk 'BEGIN{printf "This is a transcript \n" }  {printf $2 "\t" $6 "\n"}' student.txt  
#awk命令只要检测不到完整的单引号不会执行,所以这个命令的换行不用加入“\”,就是一行命令
#这里定义了两个动作
#第一个动作使用BEGIN条件,所以会在读入文件数据前打印“这是一张成绩单”(只会执行一次)第二个
动作会打印文件的第二字段和第六字段

[root@localhost ~]# awk 'END{printf "The End \n" } {printf $2 "\t" $6 "\n"}' student.txt
#在输出结尾输入“The End”,这并不是文档本身的内容,而且只会执行一次

1.1.2关系运算符

假设我想看看平均成绩大于等于87分的学员是谁,就可以这样输入命令:例子1:
[root@localhost string]# cat student.txt 
id      name    esex    makr
1       qq      aa      34
2       xx      cc      45
3       tt      vv      55
[root@localhost string]# cat student.txt | grep -v name | awk '$4 >= 40 {printf $2 "\n" }'
xx
tt
[root@localhost ~]#  awk '$2 ~ /Sc/ {printf $6 "\n"}' student.txt  
#如果第二字段中输入包含有“Sc”字符,则打印第六字段数据85.66这里要注意在awk中,使用“//”包含的字符
串,awk命令才会查找。也就是说字符串必须用“//”包含,awk命令才能正确识别。
~ 和 !~ 匹配正则表达式和不匹配正则表达式 


有$的话  必须使用~ 进行正则匹配

1.1.3正则表达式

如果要想让awk识别字符串,必须使用“//”包含,例如:例子1:
[root@localhost ~]# awk '/Liming/ {print}' student.txt
#打印Liming的成绩
当使用df命令查看分区使用情况是,如果我只想查看真正的系统分区的使用状况,而不想查看光盘和临时分区
的使用状况,则可以:例子2:
[root@localhost ~]# df -h | awk '/sda[0-9]/ {printf $1 "\t" $5 "\n"} ' 
#查询包含有sda数字的行,并打印第一字段和第五字段

1.2awk内置变量 

[root@localhost ~]# cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN {FS=":"} {printf $1 "\t" $3 "\n"}' 


[root@localhost ~]# cat /etc/passwd | grep "/bin/bash" | \awk 'BEGIN {FS=":"} {printf $1 
"\t" $3 "\t 行号:" NR "\t 字段数:" NF "\n"}'
#解释下awk命令
#开始执行{分隔符是“:”} {输出第一字段和第三字段输出行号(NR值)字段数(NF值)} 
root    0        行号:1         字段数:7 
user1   501      行号:2         字段数:7


如果我只想看看sshd这个伪用户的相关信息,则可以这样使用:
[root@localhost ~]# cat /etc/passwd | awk 'BEGIN {FS=":"} $1=="sshd" {printf $1 "\t" $3 "\t 行号:"NR "\t 字段数:"F "  \n"}'   
#可以看到sshd伪用户的UID是74,是/etc/passwd文件的第28行,此行有7个字段

1.3awk流程控制

加和

[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成绩的总分

我们解释下这个命令。“NR==2{php1=$3}”(条件是NR==2,动作是php1=$3)这句话是指如果输入数据是第二行
(第一行是标题行),就把第二行的第三字段的值赋予变量“php1”。“NR==3{php2=$3}”这句话是指如果输入数
据是第三行,就把第三行的第三字段的值赋予变量“php2”。“NR==4{php3=$3;totle=php1+php2+php3;print 
"totle php is " totle}”(“NR==4”是条件,后面{}中的都是动作)这句话是指如果输入数据是第四行,就把
第四行的第三字段的值赋予变量“php3”;然后定义变量totle的值是“php1+php2+php3”;然后输出“totle php 
is”关键字,后面加变量totle的值。

if与赋值 

假设如果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!

[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!

自定义函数

[root@localhost string]# awk 'function test(a,b) { printf a "\t" b "\n" } { test($2,$3) }' student.txt   
name    esex
qq      aa
xx      cc
tt      vv

调用脚本-f

[root@localhost ~]# vi pass.awkBEGIN   {FS=":"}{ print  $1  "\t"  $3}

[root@localhost ~]# awk -f pass.awk /etc/passwd 
root    0
bin     1
daemon  2

例子

统计日志中INFO,ERROR出现的总数,以及总记录数

awk '
BEGIN {
  FS="@"
}

{
  if ($3 == "INFO") {info_count++}
  if ($3 == "ERROR") {error_count++}

}

END {
  print "order total count:"NR   
  printf("INFO count:%d ERROR count:%d\n",info_count,error_count)
} ' demo.log_after_sort

order total count:22
INFO count:5 ERROR count:17

 

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐