AWK高端功能-数组
第1章 awk命令基础
1.1 awk命令执行过程
1、如果BEGIN 区块存在,awk执行它指定的动作。 2、awk从输入文件中读取一行,称为一条输入记录。如果输入文件省略,将从标准输入读取 3、awk将读入的记录分割成字段,将第1个字段放入变量$1中,第2个字段放入$2,以此类推。$0表示整条记录。字段分隔符使用shell环境变量FS或由参数指定。 4、把当前输入记录(数据行)依次与每一个awk命令中awk条件比较,看是否匹配,如果相匹配,就执行对应的动作。如果不匹配,就跳过对应的动作,直到比较完所有的awk命令。 5、当一条输入记录比较了所有的awk命令后,awk读取输入的下一行,继续重复步骤3和4,这个过程一直持续,直到awk读取到文件尾。 6、当awk读完所有的输入行后,如果存在END,就执行相应的动作。
1.2 awk中模式与动作
'pattern{action}'
1.2.1 在awk眼中的行与列
field 字段,列
record 记录,行
1.3 awk默认有一把“菜刀”
空格系列 (单独的空格,连续的空格,tab键)
-F 指定分隔符
-vFS
FS == field sep 每一列的分隔符
OFS ==output field sep 输出每一列的时候使用的分隔符
1.4 awk的内置变量
变量 |
含义 |
英文全写 |
FS |
每一列的分隔符 |
field sep |
NF |
每一行有多少列 |
number of field |
OFS |
输出每一列的时候使用的分隔符 |
output field sep |
NR |
记录号 行号 |
number of record |
RS |
每一行的分隔符(每一行的结束标记) |
|
$数字 |
取某一列 |
|
$0 |
取出这一行 |
1.4.1 $NF的使用
$NF 表示最后一列,(NF-1)表示倒数第二列,以此类推。
[root@znix ~]# awk -F: '{print NF}' passwd.txt 7 7 …… [root@znix ~]# awk -F: '{print $NF}' passwd.txt /bin/bash /sbin/nologin /sbin/nologin [root@znix ~]# awk -F: '{print $(NF-1)}' passwd.txt /root /bin /sbin
1.5 【练习题】awk如何使用正则?
1) 显示Xiaoyu的姓氏和ID号码
2) 显示所有ID号码最后一位数字是1或5的人的全名
3) 姓氏是Zhang的人,显示他的第二次捐款金额及她的名字
4) 显示Xiaoyu的捐款.每个值时都有以$开头.如$520$200$135
1.5.1 环境准备
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
1.5.1.1 内容释义:
第一列是姓氏
第二列是名字
第一第二列合起来就是姓名
第三列是对应的ID号码
最后三列是三次捐款数量
1.5.2 显示出第二列中包含X 的。
$2~表示第二列所有的内容。 ~表示所有
在这里X比较特殊,是大写的,awk中区分大小写。
[root@znix files]# awk '$2~/X/' reg.txt Zhang Xiaoyu 390320151 :155:90:201 Wang Xiaoai 3515064655 :50:95:135
1.5.3 显示Xiaoyu的姓氏和ID号码
[root@znix files]# awk '$2~/Xiaoyu/{print $1,$3}' reg.txt Zhang 390320151
1.5.4 显示所有ID号码最后一位数字是1或5的人的全名
[root@znix files]# awk '$3~/(1|5)$/{print $1,$2}' reg.txt [root@znix files]# awk '$3~/[15]$/{print $1,$2}' reg.txt Zhang Xiaoyu Wu Waiwai Wang Xiaoai Li Youjiu Lao Nanhai
1.5.5 姓氏是Zhang的人,显示他的第二次捐款金额及她的名字
先找到,再进行输出。(NF-1) 表示倒数第二列。
[root@znix files]# awk -F "[ :]+" '$1~/Zhang/{print $2,$(NF-1)}' reg.txt Dandan 100 Xiaoyu 90
1.5.6 显示Xiaoyu的捐款.每个值时都有以$开头.如$520$200$135
tr 命令进行替换,格式比较简单tr "要替换什么" "替换成什么"
[root@znix files]# awk '$2~/Xiaoyu/{print $4}' reg.txt |tr ":" "$" $155$90$201 [root@znix files]# awk '$2~/Xiaoyu/{gsub(/:/,"$",$NF);print $NF}' reg.txt $155$90$201
1.6 awk中的$0是什么鬼?
$0表示文件中整条记录(行)的内容,在这里加$0 与不加$0 相同。
[root@znix files]# awk '/Zhang/' reg.txt Zhang Dandan 41117397 :250:100:175 Zhang Xiaoyu 390320151 :155:90:201 [root@znix files]# awk '$0~/Zhang/' reg.txt Zhang Dandan 41117397 :250:100:175 Zhang Xiaoyu 390320151 :155:90:201
1.7 awk中的替换
在awk中,可以用来替换的有三个函数:sub gsub gensub
1.7.1 使用gusb 函数进行替换
gsub(r, s [, t])
r /找谁/
s "替换成什么"
[] 替换那个部分的
表示为: gsub(/找谁/,"替换成什么",替换那个部分的)
1.7.2 替换文本中的内容
题目:显示Xiaoyu的捐款.每个值时都有以$开头.如$520$200$135
中间使用分号分割 ;
[root@znix files]# awk '{gsub(/:/,"$",$NF);print $0}' 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@znix files]# awk '$2~/Xiaoyu/{gsub(/:/,"$",$NF);print $NF}' reg.txt $155$90$201
1.8 【练习题】判断当前系统上所有用户的shell是否为可登录shell(即用户的shell不是/sbin/nologin),如果是显示用户名字
不包含:!,在awk中不包含可以使用! 表示。
$NF 表示这个文件的最后一列
-F 将分隔符指定为:
[root@znix ~]# awk -F: '$NF!~/nologin$/{print $1}' /etc/passwd root sync shutdown halt clsn oldgirl test stu01 stu02 stu03 znix
1.8.1 【对齐】输出的结果更美观整齐--column命令
-t -t参数让他对齐。
[root@znix files]# awk 'BEGIN{print "姓","名"}{print $1,$2}' reg.txt |column -t 姓 名 Zhang Dandan Zhang Xiaoyu Meng Feixue Wu Waiwai Liu Bingbing Wang Xiaoai Zi Gege Li Youjiu Lao Nanhai
第2章 awk中BEGIN 和 END
2.1 怎么把正则表达式作为条件
BEGIN:开始
里面的内容会在awk读取文件之前运行
在BEGIN里面定义awk的内置变量
END
END{} 里面放入内容,在读取完文件内容后执行
先计算,在END里面输出结果
先计算再输出
2.1.1 【一个栗子】执行完输出后,再输出一个“结束”
[root@znix files]# awk '{print $0}END{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 结束
2.2 【企业案例】统计/etc/services文件里面的空行数量
2.2.1 使用awk的END模式
前面的i++先进行计算,再输出结果。
i=i+1 与i++ 相同。
[root@znix ~]# awk '/^$/{i=i+1}END{print i}' /etc/services 16 [root@znix ~]# awk '/^$/{i++}END{print i}' /etc/services 16
2.2.2 查看i++的执行过程
i++与i=i+1相同。
i=i+$0 累计相加 计算总和
i=i+1 i++ 计数
[root@znix ~]# awk '/^$/{i++;print i}' /etc/services 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
2.2.3 其他方法:
uniq -c uniq 命令把相邻两行一样的合并,-c为统计出现的次数
[root@znix ~]# awk '/^$/' /etc/services|uniq -c 16 [root@znix ~]# awk '/^$/' /etc/services|wc -l 16
2.3 【案例】seq 100 >num.txt ,计算这个文件每一行相加的结果
i=i+$0 累计相加 计算总和
i=i+1 i++ 计数
没有赋初始值的时候
i++ 先返回0,再加1,第二次调用的时候先返回1,再加1,以此类推
[root@znix ~]# awk '{i=i+$0}END{print i}' num.txt 5050
第3章 awk数组
3.1 数组是用来做什么的?
分类计算,用于统计。
3.1.1 他能够干些什么?
统计日志文件中 图片.jpg 出现了多少次
统计日志文件中 图片.png 出现了多少次
统计更累的信息
3.2 数组详解---"酒店"
假设我们有一个酒店
酒店<===>hotel 酒店里面有几个房间110,119,120,114,401这几个房间。 酒店的110房间<===> hotel[110] 酒店的119房间<===> hotel[119] 酒店的120房间<===> hotel[121]
酒店房间里面入住客人
3.2.1 如何查看房间里住的是哪位客人?
[root@znix files]# awk 'BEGIN{hotel[110]="lidao" ;hotel[119]="tanjiaoshou";hotel[121]="taojin";print hotel[110],hotel[121],hotel[119]}' lidao taojin tanjiaoshou
3.2.2 使用for语句,对酒店进行循环/查房
awk 'BEGIN{hotel[110]="lidao" ;hotel[119]="tanjiaoshou";hotel[121]="taojin"; for(pol in hotel) print pol,hotel[pol] }'
格式:
for(变量 in 数组) 使用变量对酒店进行循环/查房
print pol,hotel[pol] :
pol 得到-房间的号码
hotel[pol] 哪个酒店的哪个房间
[root@znix files]# awk 'BEGIN{hotel[110]="lidao" ;hotel[119]="tanjiaoshou";hotel[121]="taojin" > for(pol in hotel) > print pol,hotel[pol] > }' 110 lidao 121 taojin 119 tanjiaoshou
3.3 【企业面试题】统计域名访问次数(去重统计)。处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)
http://www.nmtui.com/index.html http://www.nmtui.com/1.html http://post.nmtui.com/index.html http://mp3.nmtui.com/index.html http://www.nmtui.com/3.html http://post.nmtui.com/2.html
3.3.1 方法一:sort uniq
uniq 命令 把相邻两行一样的合并
[root@znix ~]# awk -F '[/]+' '{print $2}' www.txt |uniq -c 2 www.nmtui.com 1 post.nmtui.com 1 mp3.nmtui.com 1 www.nmtui.com
sort 排序,默认是按照字母的顺序
[root@znix ~]# awk -F '[/]+' '{print $2}' www.txt |sort mp3.nmtui.com post.nmtui.com www.nmtui.com www.nmtui.com www.nmtui.com
3.3.2 方法2 awk数组
3.3.2.1 第一步 取出域名
[root@znix ~]# awk -F '[/]+' '{print $2}' www.txt www.nmtui.com www.nmtui.com post.nmtui.com mp3.nmtui.com www.nmtui.com
3.3.2.2 第二步 显示
; 两条命令之间用分号分割。
[root@znix ~]# awk -F '/+' '{hotel[$2]++;print hotel["www.nmtui.com"]}' www.txt 1 2 2 2 3
3.3.2.3 第三步 显示结果
[root@znix ~]# awk -F '/+' '{hotel[$2]++}END{for(pol in hotel)print pol,hotel[pol]}' www.txt mp3.nmtui.com 1 post.nmtui.com 1 www.nmtui.com 3
第4章 课后题目:
两个文件 secure.zip access.zip
4.1 统计secure文件中谁在破解你的密码(统计出破解你密码的ip地址出现的次数)
4.1.1 方法一
[root@znix test]# awk '/Failed/{fa[$(NF-3)]++}END{for(pol in fa)print pol,fa[pol]}' secure-20161219|column -t 218.65.30.126 17163 218.65.30.61 17163 125.16.71.175 4 169.46.38.74 9 183.136.238.78 30 218.2.0.16 10 122.228.238.66 1 ……
4.1.2 方法二
[root@znix test]# awk '/Failed/{print $(NF-3)}' secure-20161219 |sort|uniq -c|sort -n
4.1.3 结果统计
[root@znix test]# awk '/Failed/{fa[$(NF-3)]++}END{for(pol in fa)print pol,fa[pol]}' secure-20161219|column -t|wc -l 88
4.2 统计access.log文件中对ip地址去重并统计重复数
[root@znix test]# awk '{hotel[$1]++}END{for(pol in hotel)print pol,hotel[pol]}' access.log |head -3 101.226.125.115 284 180.154.137.177 516 101.226.125.116 127
4.3 统计access.log文件中网站一共使用了多少流量
[root@znix test]# awk '{i=i+$10}END{print i}' access.log 2478496663