[toc]
awk概述
awk不是一个命令,是一门语言。
awk又叫做GNU awk,gawk
| 12
 
 | ls -l `which awk`lrwxrwxrwx. 1 root root 4 Nov 28 11:08 /usr/bin/awk -> gawk
 
 | 
平时我们都是当作命令使用,所以我们称之为单行脚本
也可以使用awk写脚本,在Linux系统中就有很多awk脚本
| 12
 
 | find /usr/share/ -type f -name '*.awk'
 
 | 
awk的使用
awk的内置变量、选项和动作
| awk内置变量 | 变量含义 | awk选项 | 选项含义 | awk动作 | 动作含义 | 
| NR | Number of Record 行号 | -F | 指定分隔符 | gsub | 替换 | 
| RS | Record Separator 行的分隔符(\n) | -v | 指定变量(内置变量、自定义变量) | print | 打印 | 
| FS | Field Separator  列的分隔符(空格) |  |  |  |  | 
| NF | Number Of Filed 每一行有多少列 |  |  |  |  | 
注意:awk输出内容使用双引号,awk输出变量使用单引号,shell输出变量使用双引号;
awk执行流程
- 读取文件之前(BEGIN{})
- 1.读取文件之前,先看命令的选项,例如 -F,-v
- 2.如果写了BEGIN{}则先在BEGIN{}中的指令
 
- 读取文件时({})
- 1.awk在读取文件时,也是一行一行的读\
- 2.读取一行之后,判断是否满足条件,如果是,则执行{对应动作}
- 3.如果不满足条件,awk继续读取下一行,直到满足条件或者到文件的最后一行
 
- 读取文件之后(END{})
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | awk 'BEGIN{xxx}{print $1}END{print 1/3}'  zls.txt
 
 
 awk -F: 'BEGIN{print "name","uid"}{print $1,$3}END{print "文件处理完成"}' /etc/passwd|column -t
 
 
 awk -F: 'BEGIN{print "name","uid","gid"}{print $1,$3,$4}END{print "sb"}' /etc/passwd|column -t
 name             uid    gid
 root             0      0
 bin              1      1
 daemon           2      2
 adm              3      4
 lp               4      7
 sync             5      0
 shutdown         6      0
 halt             7      0
 mail             8      12
 operator         11     0
 games            12     100
 ftp              14     50
 
 
 column -t
 
 | 
awk的行与列
在awk中行和列,一般不叫行和列,有专业叫法
行:记录 record
列:字段 field
awk取记录(取行)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 
 | NR:Number of Record
 
 awk 'NR==1' /etc/passwd
 root:x:0:0:root:/root:/bin/bash
 
 
 
 awk 'NR>=1 && NR<=3' /etc/passwd
 root:x:0:0:root:/root:/bin/bash
 bin:x:1:1:bin:/bin:/sbin/nologin
 daemon:x:2:2:daemon:/sbin:/sbin/nologin
 
 
 awk 'NR==1,NR==3' /etc/passwd
 root:x:0:0:root:/root:/bin/bash
 bin:x:1:1:bin:/bin:/sbin/nologin
 daemon:x:2:2:daemon:/sbin:/sbin/nologin
 
 
 awk '/zls|cls/' zls.txt
 1,zls,666
 3,cls,888
 zls,111
 
 
 awk 'NR>=3' zls.txt
 /tmp/check_2.txt
 /tmp/check_3.txt
 /tmp/check_4.txt
 /tmp/check_5.txt
 3,cls,888
 zls,111
 4,lls,999
 
 
 awk '/zls/,/cls/' zls.txt
 1,zls,666
 /tmp/check_1.txt
 /tmp/check_2.txt
 /tmp/check_3.txt
 cls
 zls
 4,lls,999
 cls
 
 
 Record Separator
 awk -vRS=','  'NR==1' zls.txt
 
 | 
awk取列
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | FS:内置变量,列分隔符  -F: = -vFS=:
 
 awk -vFS=:  '{print $1}' /etc/passwd
 
 
 awk -vFS=:  '{print $1,$NF}' /etc/passwd
 
 
 awk -F:  '{print $1"#"$2"#"$3"#"$4"#"$5"|"$6","$NF}' /etc/passwd
 
 
 awk -F: -vOFS=
 
 awk -F: '{print $0}' /etc/passwd
 
 | 
awk取行取列实战
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 
 | top -n1 |awk 'NR==1{print $5}'
 1
 
 
 awk -F= '/IPADDR/{print $2}' /etc/sysconfig/network-scripts/ifcfg-eth0
 10.0.0.61
 
 
 cat user.txt
 Zeng Laoshi       133411023        :110:100:75
 Deng Ziqi            44002231        :250:10:88
 Zhang Xinyu      877623568      :120:300:200
 Gu Linazha         11029987         :120:30:79
 Di Lireba             253097001      :220:100:200
 Jiang Shuying    535432779       :309:10:2
 Ju Jingyi             68005178         :130:280:385
 Zhang Yuqi         376788757       :500:290:33
 Wen Zhang         259872003      :100:200:300
 
 
 awk -F '[ :]+' 'BEGIN{print "姓","名","捐款数额"}$2~/Zhang/{print $2,$3,$6}' user.txt
 姓 名 捐款数额
 Zhang Xinyu 300
 Zhang Yuqi 290
 
 awk -F '[ :]+' 'BEGIN{print "姓","名","捐款数额"}$2~/Zhang/ && $3~/X/{print $2,$3,$6}' user.txt
 姓 名 捐款数额
 Zhang Xinyu 300
 
 awk -F '[ :]+' 'BEGIN{print "姓名","捐款数额"}$2~/Zhang/ && $3~/X/{print $2 $3,$6}' user.txt |column -t
 姓名        捐款数额
 ZhangXinyu  300
 
 awk -F '[ :]+' 'BEGIN{print "姓名","捐款数额"}$2~/Zhang/ && $3~/X/{print $2 $3,$(NF-1)}' user.txt |column -t
 姓名        捐款数额
 ZhangXinyu  300
 
 
 awk '$4~/^25/{print $2 $3,$4}' user.txt
 DiLireba 253097001
 WenZhang 259872003
 
 
 awk '$3~/1$|3$/{print $1$2,$3}' user.txt
 ZengLaoshi 133411023
 DengZiqi 44002231
 DiLireba 253097001
 WenZhang 259872003
 
 awk '$3~/(1|3)$/{print $1$2,$3}' user.txt
 ZengLaoshi 133411023
 DengZiqi 44002231
 DiLireba 253097001
 WenZhang 259872003
 
 awk '$3~/[13]$/{print $1$2,$3}' user.txt
 ZengLaoshi 133411023
 DengZiqi 44002231
 DiLireba 253097001
 WenZhang 259872003
 
 
 awk -F: -vOFS='$' '{print $2,$3,$4}' zls.txt
 
 awk '{gsub(/:/,"$",$4)}' user.txt
 
 awk  '{gsub(/:/,"$");print $0}' user.txt
 Zeng Laoshi       133411023        $110$100$75
 Deng Ziqi            44002231        $250$10$88
 Zhang Xinyu      877623568      $120$300$200
 Gu Linazha         11029987         $120$30$79
 Di Lireba             253097001      $220$100$200
 Jiang Shuying    535432779       $309$10$2
 Ju Jingyi             68005178         $130$280$385
 Zhang Yuqi         376788757       $500$290$33
 Wen Zhang         259872003      $100$200$300
 
 awk  '{gsub(/:/,"$",$4);print $0}' user.txt
 Zeng Laoshi 133411023 $110 :100:75
 Deng Ziqi 44002231 $250 :10:88
 Zhang Xinyu 877623568 $120 :300:200
 Gu Linazha 11029987 $120 :30:79
 Di Lireba 253097001 $220 :100:200
 Jiang Shuying 535432779 $309 :10:2
 Ju Jingyi 68005178 $130 :280:385
 Zhang Yuqi 376788757 $500 :290:33
 Wen Zhang 259872003 $100 :200:300
 
 function gsub(){
 $1
 $2
 $3
 xxxx
 }
 
 gsub(xx,aaa,d)
 
 gsub("被替换的内容","替换的新内容")
 gsub("被替换的内容","替换的新内容",第N列)
 
 
 ifconfig |awk -vRS='[^0-9]+' '$0>=1 && $0<=255'
 10
 61
 255
 255
 255
 10
 255
 6
 80
 20
 29
 3
 64
 20
 29
 3
 2
 5
 2
 6
 1
 172
 16
 1
 61
 255
 255
 255
 172
 16
 1
 255
 6
 80
 20
 29
 3
 9
 64
 20
 29
 3
 9
 46
 9
 117
 29
 7
 73
 127
 1
 255
 6
 1
 128
 10
 
 | 
awk的模式与动作
| 1
 | awk -F: 'NR==1{print 1 $1,$3}' /etc/passwd
 | 
上面这条命令我们可以看到, 'NR==1{print $1,$3}' 可以理解为, '模式{动作}'== '条件{指令}'
awk中的模式
- 正则表达式 | 12
 3
 4
 5
 
 | '/正则表达式/flag'
 '$1~/正则表达式/flag'
 '$1!~/正则表达式/flag'
 只不过我们在awk中很少使用flag
 
 |  
 
- 比较表达式 | 12
 3
 4
 5
 
 | NR==1NR>=10
 NR<=100
 NR>=1 && NR<=10
 $1>=100
 
 |  
 
- 范围模式 | 12
 3
 4
 5
 6
 7
 
 | NR==10,NR==20
 
 '/root/,/zls/'
 '/从哪个字符串所在行/,/到那个字符串所在行/'
 
 '$1~/oo/,$1~/zl/'
 
 |  
 
- 特殊模式 - BEGIN 和 END 
awk中的动作
在awk中,我们最常用的动作就是 print
当然我们还有别的动作可以使用:
| 1
 | useradd name;pass=`echo $RANDOM|md5sum|cut -c 1-10`;echo $pass|passwd --stdin name;echo $pass:$user >> /tmp/user.txt
 | 
BEGIN模式
使用BEGIN模式,需要成双成对出现:BEGIN{}
BEGIN{}中,大括号里的内容,会在读取文件内容之前执行
主要应用场景:
END模式
END{}要比BEGIN{}重要一些,BEGIN{}可有可无,计算其实可以放在读取文件的时候,也可以执行
END{}中,大括号里面的内容,会在awk读取完文件的最后一行后,进行处理
作用:一般我们使用END{}来显示对日志内容分析后的一个结果 当然,还有其他功能,比如文件读取完了,可以显示一些尾部信息
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 
 | awk '{hang++;print hang}' /etc/services
 1
 ...
 11176
 
 
 awk '{hang++}END{print hang}' /etc/services
 11176
 
 
 awk 'END{print NR}' /etc/services
 11176
 
 
 wc -l /etc/services
 11176 /etc/services
 
 grep -c '.*' /etc/services
 11176
 
 sed -n '$=' /etc/services
 11176
 
 
 
 awk '/^$/{print}' /etc/services | wc -l
 17
 awk '/^$/{i++}END{print i}' /etc/services
 17
 
 
 zcat blog.xxx.com+access.log.gz | awk '$10~/200/{code++}END{print code}'
 
 
 
 cat user.txt
 姓名 年龄
 大萨 23
 长囧 18
 西施 99
 
 
 
 n=0
 for line in `cat user.txt`;do
 if [[ $line =~[0-9]+ ]];then
 ((n+=$line))
 fi
 done
 echo $n
 
 
 awk 'NR>1{print $2}' user.txt
 23
 18
 99
 awk 'NR>1{n+=$2}END{print n}' user.txt
 
 
 
 zcat blog.xxx.com_access.log.gz | awk 'BEGIN{print "状态码200的次数","总流量"}$10~/200/{code++;bute+=$11}END{print code,byte}' | column -t
 状态码200的次数  总流量
 3100              15645341
 
 
 awk '
 BEGIN{
 print "状态码200的次数","总流量"
 }
 $10~/200/{
 code++;bute+=$11
 }
 END{
 print code,byte
 }' | column -t
 
 
 
 zcat blog.xxx.com_access.log.gz | awk '$10~/^[45]/{i++;n+=$11}END{prnt i,n}'
 564 342332
 
 
 
 zcat blog.xxx.com_access.log.gz |awk '
 BEGIN{
 print "状态码","总流量"
 }
 $10~/^2/{i1++;n1+=$11}
 $10~/^3/{i2++;n2+=$11}
 $10~/^4/{i3++;n3+=$11}
 $10~/^5/{i4++;n4+=$11}
 END{
 print "200次数"i1,"200的流量"n1
 print "3xx次数"i2,"3xx的流量"n2
 print "4xx次数"i3,"4xx的流量"n3
 print "5xx次数"i4,"5xx的流量"n4
 }'|column -t
 
 
 
 | 
awk数组
awk的数组赋值
| 12
 
 | awk 'BEGIN{array[0]="hqw";arrat[1]="hbb"}'
 
 | 
awk数组的取值
| 12
 
 | awk 'BEGIN{array[0]="hqw";array[1]="hbb";print array[0],array[1]}'
 
 | 
数组的循环
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 
 | for (条件){动作
 }
 for 条件;do
 动作
 done
 
 
 awk 'BEGIN{array[0]="hqw";array[1]="hbb";for(num in array){print num}}'
 0
 1
 
 awk 'BEGIN{array[0]="hqw";array[1]="hbb";for(num in array){print array[num]}}'
 hqw
 hbb
 
 
 zcat blog.xxx.com_access.log.gz | awk '{array[$1]++}END{for(ip in array){print ip,array[ip]}}'
 
 array[$1]++
 
 
 
 zcat blog.xxx.com_access.log.gz | awk '{ip[$1]++;liuliang[$1]+=$11}END{for (i in ip){print i,ip[i],liuliang[i]}}'
 
 i
 ip[i]
 liuliang[i]
 
 | 
awk判断
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | if(条件){
 动作
 }
 
 
 if(条件){
 动作
 }else{
 动作
 }
 
 if(条件){
 动作
 }else if(条件){
 动作
 }else{
 动作
 }
 
 
 
 df -h| awk -F '[ %]+' 'NR==2{if($5>70){print "磁盘空间不足"}else{print "磁盘空间充足,现在的使 用率是:"$5"%"}}'
 
 |