在《运维实例:批量统计分区占用情况,并形成Excel报表》这篇文章里,我们用到了一条awk命令
$ df -hT
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda1 ext4 20G 4.9G 14G 27% /
tmpfs tmpfs 127G 0 127G 0% /dev/shm
/dev/sda3 ext4 515G 45G 445G 10% /export
/dev/sdb ext4 1.1T 476G 570G 46% /export/Data/jd_search
$ df -hT | grep /export | egrep -v '(bigtable)' | awk '{ print $5, $7 }'
445G /export
570G /export/Data/jd_search
$ df -hT | grep /export | egrep -v '(bigtable)' | awk 'END{ if(NR=1) print $5, $7; else if(NR=2 && $7=="/export/Data/jd_search") print $5, $7}'
570G /export/Data/jd_search
下面这条awk大意就是,如果有/export/Data/jd_search分区,则返回这个分区的剩余空间,否则就返回/export分区的剩余空间。
先说说这个END
在Unix awk中两个特别的表达式,BEGIN和END,这两者都可用于pattern中(参考前面的awk语法),提供BEGIN和END的作用是给程序赋予初始状态和在程序结束之后执行一些扫尾的工作。
任何在BEGIN之后列出的操作(在{}内)将在Unix awk开始扫描输入之前执行,而END之后列出的操作将在扫描完全部的输入之后执行。因此,通常使用BEGIN来显示变量和预置(初始化)变量,使用END来输出最终结果。
所以,下方命令可以用来统计文件的行数
$ awk 'END{print NR}' test1.sh
注意,这条命令里,如果没有END这个参数,则NR并不会输出行数。为什么,下面介绍一下NR。
NR,NF,FNR的介绍
NR表示从awk开始执行后,按照记录分隔符读取的数据次数,默认的记录分隔符为换行符,因此默认的就是读取的数据行数,NR可以理解为Number of Record的缩写。
在awk处理多个输入文件的时候,在处理完第一个文件后,NR并不会从1开始,而是继续累加,因此就出现了FNR,每当处理一个新文件的时候,FNR就从1开始计数,FNR可以理解为File Number of Record。
NF表示目前的记录被分割的字段的数目,NF可以理解为Number of Field。
比如现在AWK处理到第五行。第一行没有进行操作,2,3,4,5行进行了操作,那么NR=5,FNR=4
NR==FNR 表示从起始行到当前行,awk都进行了操作,比如修改,添加等等
简单来说,NR就是当前读取多少行,FNR就是当前修改了多少行,FNR<=NR
下方是一个演示
$ cat class1
zhaoyun 85 87
guanyu 87 88
liubei 90 86
$ cat class2
caocao 92 87 90
guojia 99 96 92
$ awk '{print FILENAME,"NR="NR,"FNR="FNR,"$"NF"="$NF}' class1 class2
class1 NR=1 FNR=1 $3=87
class1 NR=2 FNR=2 $3=88
class1 NR=3 FNR=3 $3=86
class2 NR=4 FNR=1 $4=90
class2 NR=5 FNR=2 $4=92