[toc]
awk概述
awk
不是一个命令,是一门语言。
awk
又叫做GNU awk,gawk
1 2
| ls -l `which awk` lrwxrwxrwx. 1 root root 4 Nov 28 11:08 /usr/bin/awk -> gawk
|
平时我们都是当作命令使用,所以我们称之为单行脚本
也可以使用awk写脚本,在Linux系统中就有很多awk脚本
1 2
| 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{})
1 2 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取记录(取行)
1 2 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取列
1 2 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取行取列实战
1 2 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中的模式
正则表达式
1 2 3 4 5
| '/正则表达式/flag' '$1~/正则表达式/flag' '$1!~/正则表达式/flag' 只不过我们在awk中很少使用flag
|
比较表达式
1 2 3 4 5
| NR==1 NR>=10 NR<=100 NR>=1 && NR<=10 $1>=100
|
范围模式
1 2 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{}来显示对日志内容分析后的一个结果 当然,还有其他功能,比如文件读取完了,可以显示一些尾部信息
1 2 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的数组赋值
1 2
| awk 'BEGIN{array[0]="hqw";arrat[1]="hbb"}'
|
awk数组的取值
1 2
| awk 'BEGIN{array[0]="hqw";array[1]="hbb";print array[0],array[1]}'
|
数组的循环
1 2 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判断
1 2 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"%"}}'
|