4.1特点与应用场景
awk
一门语言,类似于C语言 过滤,统计,计算 过滤,统计日志
4.2 awk内置变量
内置变量 | 示例 | |
NR | Number or Record 记录号,行号 | |
NF | Number of Field 每行有多个字段(列) $NF表示最后一列 | awk '{print $NF}' 文件名 |
FS | -F: ===-v FS=: Field Separator 字段分隔符,每个字段结束标记 | |
OFS | Output Field Separator 输出字段分隔符,(awk显示每一列的时候,每一列之间通过什么分割,默认是空格) | awk -F: -v OFS=: '{print $NF,$2,$3,$4,$5,$6,$1}' 文件名 |
4.3行与列
名词 | awk中叫法 | 一些说明 |
行 | 记录record | 每一行默认通过回车分割 |
列 | 字段域field | 每一列默认通过空格分割 |
awk中行和列结束标记都是可以修改的 |
1)取行
awk | 示例 | |
NR==1 | 取出某一行 | awk 'NR==1' access.log.20220304000301 |
NR>1&&NR<=5 | 取出1到5行范围 | |
/oldboy/ | ||
/101/,/105/ | ||
符号 | > < >= <= == != |
2)取列
-F 指定分隔符 指定每一列结束标记(默认是空格,连续的空格,tab键) $数字 取出某一列,注意:在awk中$内容一个意思 表示取出某一列 $0整行的内容, {print xxx} $NF表示最后一列(示例) awk '{print $NF}' access.log.20220304000301
取网卡地址
只取个ip地址
3)小结
行与列名称 awk取行与列,指哪打哪 取出网卡ip地址
4.4 swk 模式匹配
谁可以作为awk的条件
awk | -F"{/}+" | 'NR==3{print $3}' |
命令 | 选项 | '条件{动作}' |
'模式{干啥}' | ||
'模式{动作}' | ||
'pattern{action}' |
1)比较表达式-参考上面取行部分
2)正则:
支持扩展正则 awk可以精确到某一列,某一行中包含/不包含.....内容。 ~包含 !~不包含
正则 | awk正则 | |
^表示以....开头的行 | 某一列的开头 $3~/^oldoy/ | |
$表示以.....结尾的行 | 某一列的结尾$4~/lidao$/ | |
^$表示空行 | 某一列是空的 很少用 |
#找出 第3列以2开头的行,并显示第1,3和最后一列
找出 第3列以1或2开头的行,并显示第1列,第3列和最后一列
还有这几种写法
3)表示范围
/哪里开始/,/哪里结束/ 常用 NR==1,NR==5 从第1行开始到第5行结束 类似于sed -n '1,5p' #显示指定时间(11:02:00到11:02:30)范围内容的ip地址和用户访问uri column -t(自动对齐) awk '/11:02:00/,/11:02:30/{print $1}' access.log.20220304000301 awk '/11:02:00/,/11:02:30/{print $1,$7,$9,$10}' access.log.20220304000301 |column -t
4)特殊模式BEGIN{}和END{}
模式 | 含义 | 应用场景 |
BEGIN{} | 里面的内容会在awk读取文件之前执行 | 1)进行简单统计,计算,不涉及读取文件(常见) 2)用来处理文件之前,添加个表头(了解) 3)用来定义awk变量(很少用,因为可以用-v) |
END{} | 里面的内容会在awk读取文件之后执行 | 1)awk进行统计,一般过程;先进行计算,最后END里面输出结果(常见) 2)awk使用数组,用来输出数组结果。(常见) |
END{}统计计算:
统计方法
统计方法 | 简写形式 | 应用场景 |
i=i+1 | i++ | 计数,统计次数 |
sum=sum+??? | sum+=??? | 求和,累加 |
注意:i,sum都是变量 |
#统计/etc/services 里面有多少个空行 awk '/^$/' /etc/services
统计有多少空行
awk '/^$/{i++}END{print i}' /etc/services
#seq 100 求和1+2+3.。。+100 awk实现 seq 100 |awk '{sum=sum+$1}END{print sum}'
求和显示过程
seq 100 |awk '{sum=sum+$1;print sum}END{print sum}'
4.5 awk数组
统计日志:类似于
统计次数:统计每个ip出现次数,统计每种状态码出现次数,统计系统中每个用户被攻击的次数,统计攻击者ip出现次数
累加求和:统计每个ip消耗的流量。
shell数组 | awk数组 | ||
形式 | array[0]=oldboy array[1]=liao | array[0]=oldboy array[1]=liao | |
使用 | echo ${array[0]} ${array[1]} | print array[0] array[1] | |
批量输出数组内容 | for i in ${array[*]} do echo $i done | for(i in array) print array[i] | awk数组专用循环,变量获取到的是数组的下标 |
#awk中字母 会被识别为变量,如果只是想使用字符串需要使用双引号引起来 awk 'BEGIN{a[0]=oldboy;a[1]=liao; print a[0],a[1]}'
所以无结果
数字和加双引号可以正常显示
awk数组专用循环打印
[root@heimajinpai ~]# awk 'BEGIN{a[0]=12306;a[1]="liao"; for(i in a) print i }' 0 1 [root@heimajinpai ~]# awk 'BEGIN{a[0]=12306;a[1]="liao"; for(i in a) print a[i] }' 12306 liao [root@heimajinpai ~]# awk 'BEGIN{a[0]=12306;a[1]="liao"; for(i in a) print i,a[i] }' 0 12306 1 liao
案例:
http://www.etantian.org/index.html http://www.etantian.org/1.html http://post.etantian.org/2.html http://mp3.etantian.org/3.html http://www.etantian.org/4.html http://post.etantian.org/5.html [root@heimajinpai test]# awk -F"[/]+" '{print $2}' url.txt www.etantian.org www.etantian.org post.etantian.org mp3.etantian.org www.etantian.org post.etantian.org [root@heimajinpai test]# awk -F"[/.]+" '{print $2}' url.txt www www post mp3 www post [root@heimajinpai test]# awk -F"[/.]+" '{array[$2]++}END{for(i in array)print i,array[i]}' url.txt www 3(出现的次数) mp3 1(出现的次数) post 2(出现的次数)
#array[]++ 你要统计什么 [] 里面就是什么(某一列) awk -F"[/.]+" '{array[$2]++}END{for(i in array)print i,array[i]}' url.txt
#统计access.log中 每种状态码出现的次数(方式一) awk '{array[$10]++}END{for(i in array)print i,array[i]}' access.log.20220304000301 |sort -rnk2
#统计access.log中 每种状态码出现的次数(方式一) awk '$10~/[0-9][0-9][0-9]/{array[$10]++}END{for(i in array)print i,array[i]}' access.log.20220304000301 |sort -rnk2注意:使用awk统计日志,尽量精确匹配。
4.6 for循环
for n in 1 2 3 do echo $n done
for(i=1;i<10;i++) do echo $i done | for(i=1;i<10;i++) print i | awk for循环用来循环每个字段 |
#1+100 [root@heimajinpai nginxlog]# awk 'BEGIN{for(i=1;i<=100;i++)sum+=i;print sum}' 5050 [root@heimajinpai nginxlog]#
4.7if 判断
统计磁盘空间使用率,如果大于70%,则提示磁盘空间不足,并显示磁盘分区,磁盘使用率,磁盘挂载点
df -h |awk -F"[ %]+" 'NR>1{if($5>=70)print "disk not enough"}'
df -h |awk -F"[ %]+" 'NR>1{if($5>=1)print "disk not enough",$1,$5,$NF}'
注意:awk使用多个条件的时候 第1个条件可以放在 ‘条件{动作}’ 第2个条件 一般使用if
面试题:统计这段语句中,单词中字符小于6的单词,显示出来。
4.9总结
个人网站:http://www.heimajinpai.cn/wordpress/
微信公众号:黑马金牌编程