awk执行过程
awk取行
awk取列
awk过滤(模式与动作)
awk数组
awk判断
awk循环
.1 awk概述
awk 语言 单行脚本
gnu awk gawk
[root@m01 /server/files]# awk -F: 'BEGIN{print "name","UID"}{print $1,$3}END{print "文件处理完成"}'
/etc/passwd |column -t
name UID
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
operator 11
games 12
ftp 14
nobody 99
systemd-network 192
dbus 81
polkitd 999
tss 59
abrt 173
sshd 74
postfix 89
oldboy 1000
ntp 38
lidao 1001
zhuzhuzhu 1002
fourzhu 1003
aliyun 1004
openvpn 998
tcpdump 72
tomcat 53
quede_user_name666 1005
quede_user_name666-01 1006
quede_user_name666-01... 1007
nginx 997
文件处理完成
2 .awk 行与列
1) 取行
###案例01 取文件的第1行 ※※※※※
[root@m01 /server/files]# awk 'NR==1' sed.txt
101,oldboy,CEO
###案例02 取出文件中 第3行到最后一行 ※※※※※
[root@m01 /server/files]# awk 'NR>=3' sed.txt
103,李导996,COO
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
119,huiling,CFO
###案例03 取出文件中 第3行到第5行 ※※※※※
[root@m01 /server/files]# awk 'NR>=3 && NR<=5' sed.txt
103,李导996,COO
104,yy,CFO
105,feixue,CIO
#&& 并且 同时成立
#|| 或者
###案例04 模糊查询 找出文件中包含 oldboy或lidao的行 ※※※※※
[root@m01 /server/files]# awk '/oldboy|lidao/' sed.txt
101,oldboy,CEO
110,lidao,COCO
###案例05 模糊查询,表示范围 从包含oldboy的行到包含lidao的行 ※※※※※
[root@m01 /server/files]# awk '/oldboy/,/lidao/' sed.txt
101,oldboy,CEO
102,zhangya,CTO
103,李导996,COO
104,yy,CFO
105,feixue,CIO
110,lidao,COCO
###案例06 第3行到第5行
[root@m01 /server/files]# awk 'NR==3,NR==5' sed.txt
103,李导996,COO
104,yy,CFO
105,feixue,CIO
[root@m01 /server/files]# sed -n '3,5p' sed.txt
103,李导996,COO
104,yy,CFO
105,feixue,CIO
[root@m01 /server/files]#
###案例进阶07 通过RS控制每行的结束标记
[root@m01 /server/files]# awk '{print NR,$0}' sed.txt
1 101,oldboy,CEO
2 102,zhangya,CTO
3 103,李导996,COO
4 104,yy,CFO
5 105,feixue,CIO
6 110,lidao,COCO
7 119,huiling,CFO
[root@m01 /server/files]# awk -vRS=, '{print NR,$0}' sed.txt
1 101
2 oldboy
3 CEO
102
4 zhangya
5 CTO
103
6 李导996
7 COO
104
8 yy
9 CFO
105
10 feixue
11 CIO
2) 取列
awk -F
awk -vFS
#案例01 显示 /etc/passwd 第1列第3列
[root@m01 /server/files]# awk -F: '{print $1,$3}' /etc/passwd
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
#注意: 在awk中 $数字 $内容 取某一列
#案例02 显示第1列和第3列和最后一列
[root@m01 /server/files]# awk -F: '{print $1,$3,$NF}' /etc/passwd
#案例03 显示第1列和第3列和最后一列 中间通过#分割
[root@m01 /server/files]# awk -F: -vOFS=# '{print $1,$3,$NF}' /etc/passwd
root#0#/bin/bash
bin#1#/sbin/nologin
daemon#2#/sbin/nologin
adm#3#/sbin/nologin
lp#4#/sbin/nologin
sync#5#/bin/sync
shutdown#6#/sbin/shutdown
halt#7#/sbin/halt
-v 修改或设置awk变量
3) 综合 取行与取列
#案例01 取出top 命令中运行时间
[root@m01 /server/files]# top -n1 |awk -F'[ ,]+' 'NR==1{print $5}'
14:49
[root@m01 /server/files]# # '找谁{干啥}'
#案例02 取出网卡配置文件中的ip部分
[root@m01 /server/files]# awk '/IPADDR/' /etc/sysconfig/network-scripts/ifcfg-eth0
IPADDR=10.0.0.61
[root@m01 /server/files]# awk '/IPADDR/{print $0}' /etc/sysconfig/network-scripts/ifcfg-eth0
IPADDR=10.0.0.61
[root@m01 /server/files]# awk '/IPADDR/{print }' /etc/sysconfig/network-scripts/ifcfg-eth0
IPADDR=10.0.0.61
[root@m01 /server/files]# awk -F= '/IPADDR/{print $2}' /etc/sysconfig/network-scripts/ifcfg-eth0
10.0.0.61
#案例03
mkdir -p /server/files/
cat >>/server/files/reg.txt<<EOF
Zhang Dandan 41117397 :250:100:175
Zhang Xiaoyu 390320151 :155:90:201
Meng Feixue 80042789 :250:60:50
Wu Waiwai 70271111 :250:80:75
Liu Bingbing 41117483 :250:100:175
Wang Xiaoai 3515064655 :50:95:135
Zi Gege 1986787350 :250:168:200
Li Youjiu 918391635 :175:75:300
Lao Nanhai 918391635 :250:100:175
EOF
姓氏是Zhang的人,显示他的第二次捐款金额及她的名字
显示所有以41开头的ID号码的人的全名和ID号码
显示所有ID号码最后一位数字是1或5的人的全名
显示Xiaoyu的捐款.每个值时都有以$开头.如$520$200$135
#姓氏是Zhang的人,显示他的第二次捐款金额及她的名字
[root@m01 /server/files]# ##某一列中包含什么内容
[root@m01 /server/files]#
[root@m01 /server/files]# awk '$1~/Zhang/' reg.txt
Zhang Dandan 41117397 :250:100:175
Zhang Xiaoyu 390320151 :155:90:201
[root@m01 /server/files]# # $1~/Zhang/
[root@m01 /server/files]# # 第1列 匹配/包含 /Zhang/
[root@m01 /server/files]# awk -F'[ :]+' '$1~/Zhang/{print $NF-1}' reg.txt
174
200
[root@m01 /server/files]# awk -F'[ :]+' '$1~/Zhang/{print $(NF-1)}' reg.txt
100
90
[root@m01 /server/files]# awk -F'[ :]+' '$1~/Zhang/{print $1,$2,$(NF-1)}' reg.txt
Zhang Dandan 100
Zhang Xiaoyu 90
#显示所有以41开头的ID号码的人的全名和ID号码
[root@m01 /server/files]# awk '$3~/^41/' reg.txt
Zhang Dandan 41117397 :250:100:175
Liu Bingbing 41117483 :250:100:175
[root@m01 /server/files]# awk '$3~/^41/{print $1,$2,$3}' reg.txt
Zhang Dandan 41117397
Liu Bingbing 41117483
#显示所有ID号码最后一位数字是1或5的人的全名
[root@m01 /server/files]# awk '$3~/[15]$/' reg.txt
Zhang Xiaoyu 390320151 :155:90:201
Wu Waiwai 70271111 :250:80:75
Wang Xiaoai 3515064655 :50:95:135
Li Youjiu 918391635 :175:75:300
Lao Nanhai 918391635 :250:100:175
[root@m01 /server/files]# awk '$3~/(1|5)$/' reg.txt
Zhang Xiaoyu 390320151 :155:90:201
Wu Waiwai 70271111 :250:80:75
Wang Xiaoai 3515064655 :50:95:135
Li Youjiu 918391635 :175:75:300
Lao Nanhai 918391635 :250:100:175
[root@m01 /server/files]# awk '$3~/(1|5)$/{print $1,$2}' reg.txt
Zhang Xiaoyu
Wu Waiwai
Wang Xiaoai
Li Youjiu
Lao Nanhai
#每个值时都有以$开头.如$520$200$135
[root@m01 /server/files]# awk '{gsub(/:/,"$") ;print }' reg.txt
Zhang Dandan 41117397 $250$100$175
Zhang Xiaoyu 390320151 $155$90$201
Meng Feixue 80042789 $250$60$50
Wu Waiwai 70271111 $250$80$75
Liu Bingbing 41117483 $250$100$175
Wang Xiaoai 3515064655 $50$95$135
Zi Gege 1986787350 $250$168$200
Li Youjiu 918391635 $175$75$300
Lao Nanhai 918391635 $250$100$175
[root@m01 /server/files]# awk '/Wang/{gsub(/:/,"$") ;print }' reg.txt
Wang Xiaoai 3515064655 $50$95$135
gsub(/找谁/,"替换成什么")
gsub(/找谁/,"替换成什么",指定某一列)
综合应用 : 找出ifconfig命令结果中的1-255之间的数值;
ifconfig |egrep '[0-9]+' -o |awk '$0>=1 && $0<=255'
ifconfig |egrep '[0-9]+' -o |awk '$0>=1 && $0<=255'
ifconfig
#只要不是数字,就是行的结束标记
ifconfig | awk -vRS='[^0-9]+' '{print NR,$0}'
ifconfig | awk -vRS='[^0-9]+' '{print $0}'
ifconfig | awk -vRS='[^0-9]+' '$0>=1 && $0<=255'
ifconfig | awk -vRS='[^0-9]+' '$0>=200 && $0<=255'
3 模式与动作
1) 概述
awk -F: 'NR==1{print $1,$3}' /etc/passwd
'模式{动作}'
'条件{命令}'
awk中哪些可以作为条件/模式
正则表达式作为模式 匹配 '//' '$1~//' $1!~//
m 比较表达式作为模式 NR>10
m 范围模式
m 特殊模式BEGIN和END
#awk中哪些内容可以做为动作(命令)
print
awk函数: gsub
变量赋值
统计计算
2) BEGIN
案列
#1. 统计计算
[root@m01 /server/scripts]# awk 'BEGIN{ print 1/3 }'
0.333333
[root@m01 /server/scripts]#
#3. 显示标题
[root@m01 /server/scripts]# awk -F: 'BEGIN{print "name","UID"} {print $1,$3}' /etc/passwd|column -
tname UID
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
3) END{}
#案例01 统计/etc/services 中 一共有多少行
#条件: 无
#动作: i++
i=i+1 == i++ 进行计数 统计次数
[root@m01 /server/scripts]# awk '{i++}END{print i}' /etc/services
11176
wc -l /etc/services
awk 'END{print NR}' /etc/services
sed -n '$=' /etc/services
#案例02 统计 /etc/services 中空行的数量
[root@m01 /server/scripts]# awk '/^$/' /etc/services |wc -l
17
[root@m01 /server/scripts]# awk '/^$/{i++}END{print i}' /etc/services
17
[root@m01 /server/scripts]#
#案例03 统计access.log中 总共使用多少流量
[root@m01 /server/files]# cat age.txt
姓名 年龄
小胖 18
慧老师 15
康熙 99
李导 996
[root@m01 /server/files]# awk 'NR>1{i=i+$2}END{print i}' age.txt
[root@m01 /server/files]# awk 'NR>1{i=i+$2}END{print i}' age.txt
1128
#案例04 统计access.log中 状态码是200的次数,及状态码为200的流量总和
#条件(模式) : 状态码是200
#动作:
统计次数: i++
统计流量总和 : sum=sum+$????
#书写条件
[root@m01 /server/files]# less access.log
[root@m01 /server/files]# less access.log
[root@m01 /server/files]# #$9 状态码
[root@m01 /server/files]# #$10 大小/流量
[root@m01 /server/files]# #书写条件
[root@m01 /server/files]# #awk '$9==200' access.log
[root@m01 /server/files]# #awk '$9~/^200$/' access.log
[root@m01 /server/files]# awk '$9==200' access.log |head
#书写动作
[root@m01 /server/files]# awk '$9==200{i++ ; sum=sum+$10}END{print "200次数:"i,"200流量总和:"sum}'
access.log
200次数:142666 200流量总和:2476750207
[root@m01 /server/files]# wc -l access.log
166945 access.log
[root@m01 /server/files]# awk '$9==200{i++ ; sum=sum+$10}END{print i,sum}' access.log
142666 2476750207
[root@m01 /server/files]#
##了解
awk '
$9==200{
i++ ;
sum=sum+$10
}
END{
print i,sum
}' access.log
[root@m01 /server/files]# cat tongji.awk
#!/bin/awk
$9==200{
i++ ;
sum=sum+$10
}
END{
print i,sum
}
[root@m01 /server/files]# awk -f tongji.awk access.log
142666 2476750207
##案例05 统计access.log中 状态码是4xx或5xx的次数及的流量总
#条件 状态码是4或5开头
#动作
统计次数 i++
进行求和 sum+=$????
[root@m01 /server/files]# awk '$9~/^[45]/{ i++; sum+=$10 } END{print i,sum}' access.log
4630 1624526
[root@m01 /server/files]# awk '$9~/^2/{ i++; sum+=$10 } END{print i,sum}' access.log
142666 2476750207
[root@m01 /server/files]# awk '$9~/^3/{ i++; sum+=$10 } END{print i,sum}' access.log
19647 121930
[root@m01 /server/files]#
#最终需求: 分别统计每种状态码的次数及流量总和
awk '
$9~/^2/{ i2++; sum2+=$10 }
$9~/^3/{ i3++; sum3+=$10 }
$9~/^4/{ i4++; sum4+=$10 }
$9~/^5/{ i5++; sum5+=$10 }
END{
print "2xx:",i2,sum2;
print "3xx:",i3,sum3;
print "4xx:",i4,sum4;
print "5xx:",i5,sum5;
}' access.log|column -t
[root@m01 /server/files]# awk '
> $9~/^2/{ i2++; sum2+=$10 }
> $9~/^3/{ i3++; sum3+=$10 }
> $9~/^4/{ i4++; sum4+=$10 }
> $9~/^5/{ i5++; sum5+=$10 }
> END{
> print "2xx:",i2,sum2;
> print "3xx:",i3,sum3;
> print "4xx:",i4,sum4;
> print "5xx:",i5,sum5;
> }' access.log|column -t
2xx: 142666 2476750207
3xx: 19647 121930
4xx: 4623 1606833
5xx: 7 17693
[root@m01 /server/files]#
#统计ip
#统计 用户名
#统计域名
4. awk数组
应用场景: 分类统计
最简单: 统计每个ip出现的次数,每种状态码出现的次数, 每个用户名出现的次数, 每个攻击你网站的ip的出现次数
必用awk数组: 分类求和(分类汇总)
案列
[root@m01 /server/files]# awk '{print $1}' access.log |sort |uniq -c |sort -rn |head
12049 58.220.223.62
10856 112.64.171.98
1982 114.83.184.139
1662 117.136.66.10
1318 115.29.245.13
961 223.104.5.197
957 116.216.0.60
939 180.111.48.14
871 223.104.5.202
869 223.104.4.139
[root@m01 /server/files]# #i++
[root@m01 /server/files]#
[root@m01 /server/files]# #sum+=$....
使用awk数组
awk数组赋值
awk数组取值
awk数组批量取值
案列
# hotel[110]
hotel 数组名字
[110] 数组下标/元素名称/索引
#awk数组赋值 取值
[root@m01 /server/files]# awk 'BEGIN{hotel[110]="lidao" ; hotel[119]="pang"; print hotel[110],hotel[119]
}'
lidao pang
awk 'BEGIN{
hotel[110]="lidao" ;
hotel[119]="pang";
print hotel[110],hotel[119] }'
#awk数组批量取值
案列
[root@m01 /server/files]# awk 'BEGIN{hotel[110]="lidao" ; hotel[119]="pang";
> for(n in hotel)
> print n }'
119
110
[root@m01 /server/files]# awk 'BEGIN{hotel[110]="lidao" ; hotel[119]="pang";
for(n in hotel)
print hotel[n] }'
pang
lidao
[root@m01 /server/files]# awk 'BEGIN{hotel[110]="lidao" ; hotel[119]="pang";
for(n in hotel)
print n,hotel[n] }'
119 pang
110 lidao
[root@m01 /server/files]#
#案例01 i++
企业面试题1:统计域名访问次数
处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)
http://www.etiantian.org/index.html
http://www.etiantian.org/1.html
http://post.etiantian.org/index.html
http://mp3.etiantian.org/index.html
http://www.etiantian.org/3.html
http://post.etiantian.org/2.html
i++ #统计单一个内容
数组++ #对号入座,分类统计
array[ ]++ 下标写什么 统计什么 统计ip写ip所在那一列 $1
统计状态码 $9
[root@m01 /server/files]# awk -F'[/.]+' '{print $2}' url.txt
www
www
post
mp3
www
post
[root@m01 /server/files]# awk -F'[/.]+' '{url[$2]++}END{for(n in url) print n,url[n] }' url.txt
www 3
mp3 1
post 2
[root@m01 /server/files]#
#案例02 统计access.log中每个ip使用的流量总和
##条件 处理哪行 无
##动作 h[$1]=h[$1]+$10
eg
ip1 流量总和
ip2 流量总和
awk '{h[$1]=h[$1]+$10} END{for(ip in h)print ip,h[ip]} ' access.log
[root@m01 /server/files]# awk '{h[$1]=h[$1]+$10} END{for(ip in h)print ip,h[ip]} ' access.log |sort -
rnk2 |head
114.83.184.139 31362956
117.136.66.10 22431302
116.216.30.47 21466000
223.104.5.197 21464856
116.216.0.60 19145329
114.141.164.180 17219553
#案例03 统计每个ip出现的次数 及使用的流量
#条件: 无
#动作:
cnt[$1]++ #统计ip出现的次数
sum[$1]+=$10 #统计ip使用的流量
awk '{ cnt[$1]++; sum[$1]+=$10; } END{ for(ip in cnt) print ip,cnt[ip],sum[ip] }' access.log
|column -t |sort -rn -k2 -k3
[root@m01 /server/files]# awk '{
cnt[$1]++;
sum[$1]+=$10;
}
END{
for(ip in cnt)
print ip,cnt[ip],sum[ip]
}' access.log |column -t |sort -rn -k2 -k3
5 .awk if
# 单分支判断
if(条件) #
指令
# 双分支 判断
if($1~/root/)
print $1,$3
else
print $5,$NF
[root@m01 /server/files]# ifconfig | awk -vRS='[^0-9]+' '$0>=200 && $0<=255'
[root@m01 /server/files]# ifconfig | awk -vRS='[^0-9]+' '{if($0>=200 && $0<=255) print }'
255
255
255
255
250
255
255
#案例01 判断磁盘使用率 大于70% 如果大于 显示磁盘空间不足 如果不大于 显示正常
[root@m01 /server/files]# df -h |awk -F'[ %]+' 'NR>1{if($5>70) print "磁盘空间不足"; else print "正常" }'
正常
正常
正常
正常
正常
正常
正常
正常
[root@m01 /server/files]# df -h |awk -F'[ %]+' 'NR>1{
> if( $5>70 )
> print "no space left on device"
> else
> print "disk is ok"
> }'
disk is ok
disk is ok
disk is ok
disk is ok
disk is ok
disk is ok
disk is ok
disk is ok
6 .awk for
# awk数组专用 for循环
for(ip in h)
print ip,h[ip]
#awk 通用for循环 c语言循环
for(i=1;i<=10;i++)
print i
#案例01 计算1+....+100
[root@m01 /server/files]# awk 'BEGIN{
> for(i=1;i<=100;i++)
> sum+=i
> print sum
> }'
5050
[root@m01 /server/files]#
[root@m01 /server/files]# awk 'BEGIN{
for(i=1;i<=100;i++)
{
> sum+=i
> print sum
> }
> }'
#案例02 企业面试题:统计每个学生的总成绩和平均成绩:
#cat chengji.txt
waiwai 90 98 98 96 96 92
xiaoyu 70 77 85 83 70 89
gege 85 92 78 94 88 91
xingxing 89 90 85 94 90 95
bingbing 84 88 80 92 84 82
dandan 64 80 60 60 61 62
#条件: 无
#动作:
## 1. 求和每个人的成绩求和 sum
## 2. 计算平均成绩 sum/6
## 3. 输出
[root@m01 /server/files]# cat grade.txt
waiwai 90 98 98 96 96 92
xiaoyu 70 77 85 83 70 89
gege 85 92 78 94 88 91
xingxing 89 90 85 94 90 95
bingbing 84 88 80 92 84 82
dandan 64 80 60 60 61 62
[root@m01 /server/files]# ## 1. 求和每个人的成绩求和 sum
[root@m01 /server/files]# ## 2. 计算平均成绩 sum/6
[root@m01 /server/files]# ## 3. 输出
[root@m01 /server/files]# awk '{
> sum=$2+$3+$4+$5+$6+$7
> avg=sum/6
> print $1,avg
> }' grade.txt
waiwai 95
xiaoyu 79
gege 88
xingxing 90.5
bingbing 85
dandan 64.5
#案例03 企业面试题:统计每个学生的总成绩和平均成绩:
#cat chengji.txt
waiwai 90 98 98 96 96 92
xiaoyu 70 77
gege 85 92 78 94 88 91
xingxing 89 90 85
bingbing 84 88 80 92 84 82
dandan 64 80 61 62
[root@m01 /server/files]# cat grade2.txt
waiwai 90 98 98 96 96 92
xiaoyu 70 77
gege 85 92 78 94 88 91
xingxing 89 90 85
bingbing 84 88 80 92 84 82
dandan 64 80 61 62
[root@m01 /server/files]# awk '{for(i=2;i<=NF;i++) print $1,$i }' grade2.txt
[root@m01 /server/files]# awk '{for(i=2;i<=NF;i++) print $1,$i }' grade2.txt
waiwai 90
waiwai 98
waiwai 98
waiwai 96
waiwai 96
waiwai 92
xiaoyu 70
xiaoyu 77
gege 85
gege 92
gege 78
gege 94
gege 88
gege 91
xingxing 89
xingxing 90
xingxing 85
bingbing 84
bingbing 88
bingbing 80
bingbing 92
bingbing 84
bingbing 82
dandan 64
dandan 80
dandan 61
dandan 62
[root@m01 /server/files]#
[root@m01 /server/files]# awk '{for(i=2;i<=NF;i++) sum+=$i ;print sum }' grade2.txt
570
717
1245
1509
2019
2286
[root@m01 /server/files]# awk '{sum=0;for(i=2;i<=NF;i++) sum+=$i ;print sum }' grade2.txt
570
147
528
264
510
267
[root@m01 /server/files]# awk '{sum=0;for(i=2;i<=NF;i++) sum+=$i ;print sum/(NF-1) }' grade2.txt
95
73.5
88
88
85
66.75
[root@m01 /server/files]#
[root@m01 /server/files]# awk '{sum=0;for(i=2;i<=NF;i++) sum+=$i ;print $1,sum/(NF-1) }' grade2.txt
waiwai 95
xiaoyu 73.5
gege 88
xingxing 88
bingbing 85
dandan 66.75
awk '{
sum=0; #变量初始化 0
for(i=2;i<=NF;i++) #循环取出 第2列到最后一列
sum+=$i ;
print $1,sum/(NF-1) #循环完成,输出结果 平均数 sum/
}' grade2.txt