2.4 awk常见的内建变量(可直接使用)
FS | 列分隔符,指定每行文本的字段分隔符,默认为空格或制表符,与-F作用相同 |
OFS |
删除字段分隔符(awk显示每一列的时候,每一列之间通过什么分割,默认空格) |
NF |
当前处理的行的字段的个数 |
NR |
当前处理的行的行号(序数) |
$0 |
当前处理的行的整行内容 |
$n |
当前处理行的第n个字段(第n列) |
FILENAME |
被处理的文件名 |
RS |
行分隔符,预设值是'\n' |
[root@localhost data]# echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin [root@localhost data]# RS=':' #原本$PATH都在一行上,将RS默认行分隔符\n改为冒号后,就把这一行内容看成五行内容
2.5 awk模式匹配
命令 |
选项 |
条件{动作} |
awk |
-F"[ ]+" |
'NR==2{print $3}' |
比较符号:>< >= <= == !=
正则
范围表达式
特殊条件:BEGIN和END
2.5.1 比较表达式-参考取行部分
2.5.2 正则
//支持扩展正则
可以精确到某一列中是否包含该内容(sed和grep比较难实现)
~包含
!~不包含
正则 |
awk正则 |
^表示以……开头的行 |
某一列的开头 $3~/^root/ |
$表示以……结尾的行 |
某一列的结尾 $3~/root$/ |
^$表示空行 |
某一列是空的,很少用 |
#第三列以2开头的行 [root@localhost data]# awk -F: '$3 ~/^2/' passwd daemon:x:2:2:daemon:/sbin:/sbin/nologin rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
2.5.3 表示范围
/哪里开始/,/哪里结束/ 常用
NR==1,NR==5 从第一行开始到第五行结束 类似于sed -n '1,5p'
#显示指定时间(11:02:00到11:02:30)范围内容的IP地址 awk '/11:02:00/,/11:02:30/{print $1}' access.log
2.5.4 特殊模式BEGIN{}和END{}
模式 |
含义 |
应用场景 |
BEGIN{} |
里面的内容会在awk读取文件之前执行 | 1.统计、计算、不涉及读取文件 2.用来处理文件之前,添加个表头 3.定义awk变量(也可以用-v) |
END{} |
里面的内容会在awk读取文件之后执行 |
1.awk进行统计,一般过程:先进行计算,最后END里面输出结果 2.awk使用数组,用来输出数组结果 |
常见统计方法:
统计方法 |
简写 |
应用场景 |
i=i+1 |
i++ |
计数 |
sum=sum+??? |
sum+=??? |
求和累加 |
array[]=array[]+1 |
array[]++ |
数组分类计数 |
#统计空行 [root@localhost data]# cat test1 [root@localhost data]# awk '/^$/{i++}END{print i}' test1 10 [root@localhost data]# cat test1 |wc -l 10 #求1加到100的和 [root@localhost data]# seq 100 |awk '{sum=sum+$1}END{print sum}' 5050 [root@localhost data]# ###如果想看过程 seq 100 |awk '{sum=sum+$1;print sum}END{print sum}'
2.6 awk数组
统计日志:统计每个IP出现次数;统计每种状态码出现次数;统计系统中每个用户被攻击的次数;统计攻击者IP出现次数;
累加求和:统计每个IP消耗的流量;
shell数组 |
awk数组 |
|
形式 |
array[0]=0 array[1]=1 |
array[0]=0 array[1]=1 |
使用 |
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数组案例 [root@localhost data]# awk 'BEGIN{a[0]=123456;a[1]="stevelu";print a[0],a[1]}' 123456 stevelu [root@localhost data]# [root@localhost data]# awk 'BEGIN{a[0]=123456;a[1]="stevelu";for(i in a)print 123456 stevelu [root@localhost data]# awk 'BEGIN{a[0]=123456;a[1]="stevelu";for(i in a)print i,a[i]}' 0 123456 1 stevelu
案例
[root@localhost data]# cat test1 htttp://www.stevelu.org/index.html htttp://www.stevelu.org/1.html htttp://www.stevelu.org/2.html htttp://post.stevelu.org/index.html htttp://post.stevelu.org/1.html htttp://mp3.stevelu.org/index.html #取域名 [root@localhost data]# awk -F"[/.]+" '{print $2}' test1 www www www post post mp3 #统计各个域名出现的次数 [root@localhost data]# awk -F"[/.]+" '{a[$2]++}END{for(i in a)print i,a[i]}' test1 www 3 mp3 1 post 2 #逆序排列 [root@localhost data]# awk -F"[/.]+" '{a[$2]++}END{for(i in a)print i,a[i]}' test1|sort -rnk2 www 3 post 2 mp3 1 [root@localhost data]#
2.7 for循环
shell编程c语言for循环 |
awk for循环 |
|
for ((i=1;i<=10;i++)) do echo $i done |
for (i=1;i<=10;i++) print i |
awk for 循环用来循环每个字段 |
#100以内的求和(众多的方法之一) [root@localhost data]# awk 'BEGIN{for(i=1;i<=100;i++)sum+=i;print sum}' 5050 [root@localhost data]# awk 'BEGIN{ for(i=1;i<=100;i++) #do sum+=i; #循环的主体 print sum #循环的结果 #done }'
2.8 if判断
shell if 判断 |
awk if判断 |
|
if [ i -eq 0];then echo " " fi |
if(条件) print " " |
常用 |
if [ i -eq 0];then echo " " esle echo " " fi |
if(条件) print " " else print " " |
#显示磁盘空间不足 [root@localhost data]# df -h 文件系统 容量 已用 可用 已用% 挂载点 /dev/mapper/centos-root 10G 4.9G 5.2G 49% / devtmpfs 897M 0 897M 0% /dev tmpfs 912M 0 912M 0% /dev/shm tmpfs 912M 26M 887M 3% /run tmpfs 912M 0 912M 0% /sys/fs/cgroup /dev/sda1 1014M 179M 836M 18% /boot tmpfs 183M 32K 183M 1% /run/user/0 /dev/sr0 4.3G 4.3G 0 100% /mnt [root@localhost data]# df -h|awk -F"[ %]+" 'NR>1{if($5>70)print "disk not enou disk not enough /dev/sr0
注意:awk使用多个条件的时候 第一个条件可以放在 '条件{动作}' 第二个条件 一般使用if判断