awk工具
awk也是一个很好的数据处理工具。相比于sed常常作用于一整行的处理,awk则比较倾向于将一行分成数个字段来处理。因此,awk相当适合处理小型的数据。awk通常的运行模式是这样的:
[[email protected] opt]#awk ‘条件类型1{动作1}条件类型2{动作2}‘ filename
awk后面接两个单引号并加上大括号{}来设置想要对数据进行的处理动作。qwk可以处理后续接的文件,也可以读取来自前个命令的standardoutput。但如前面说的,awk主要是处理每一行内的数据,而默认的字段的分隔符为空格键或[tab]键。举例来说,我们用last可以将登陆者的数据读取出来,结果如下所示:
[[email protected] opt]# nl passwd | sed -n ‘$p‘
37 #This is a test
[[email protected] opt]# last -n 5
root pts/0 192.168.211.1 Tue Apr 12 09:14 still logged in
reboot system boot 2.6.32-431.el6.x Tue Apr 12 09:03 - 16:17 (1+07:13)
root pts/0 192.168.211.1 Mon Apr 11 09:57 - crash (23:05)
reboot system boot 2.6.32-431.el6.x Mon Apr 11 09:56 - 16:17 (2+06:20)
root pts/0 192.168.211.1 Mon Mar 28 21:47 - crash (13+12:09)
wtmp begins Sun Jan 24 00:22:20 2016
[[email protected] opt]# last -n 5| awk ‘{print $1 "\t" $3}‘
root 192.168.211.1
reboot boot
root 192.168.211.1
reboot boot
root 192.168.211.1
wtmp Sun
我仅想要取出账号与登陆者信息,且账号与IP之间以[tab]隔开,则会变成如下图:
[[email protected] opt]# last -n 5| grep root |awk ‘{print $1 "\t" $3}‘
root 192.168.211.1
root 192.168.211.1
root 192.168.211.1
awk最常使用的动作。通过Print的功能将字段数据列出来!字段的分隔则以空格或[tab]按键来隔开。因为不论哪一行都要处理,都要处理,因此,就不需要条件类型的限制!我们想要的是第一列和第三列,但是如上红字体的为什么和别的不一样呢?这是因为数据格式的问题。所以在使用awk的时候,要先确认一下数据,如果是连续的数据,不要有空格或[tab]在内,否则,就会出现那样的情况
另外,由上面的例子也会知道,在每一行的每个字段都是有变量名称的,那就是$1 $2等变量名称。以上面的例子来说,root就是$1,因为他是第一列!192.168.211.1是第三列,所以就是$3,后面以此类推。还有各变量,就是$0,他代表一整行数据的意思。以上面的例子来说,第一行的$0代表的就是“root”那
一行。由此可知,刚才上面五行当中,整个awk的处理流程是:
1、读入第一行,并将第一行的数据填入$0,$1,$2等变量中;
2、依据条件类型的限制,判断是否需要进行后面的动作;
3、做完所有的动作与条件类型;
4、若还有后续的“行”的数据,则重复上面1-3的步骤,直到所有的数据读完为止。
经过这样的步骤,你会知道,awk是以行为一次处理的单位,而以字段为最小的处理单位。那么awk怎么知道我到底这个数据有几行几列呢?这就需要awk的内置变量的帮忙了,
NF 每一行($0)拥有的字段总数。
NR 目前awk所处理的是“第几行”数据。
FS 目前的分隔字符,默认是空格键。
列出每一列的账号(就是$1)
列出目前处理的行数(就是awk内的NR变量)
并且说明,改行有多少字段(就是awk内的NF变量)
要注意,awk后续的所有动作是以单引号括住的,由于单引号与双引号都必须是成对的,所以,awk的格式内容如查想要以print打印时,记得非变量的文字部分,包含一小节printf提到的格式中,都需要使用双引号来定义出来,因为单引号已经是awk的命令的固定用法。
[[email protected] opt]# last -n 5| grep root |awk ‘{print $1 "\t lines:" NR "\t colums:" NF}‘
root lines:1 colums:10
root lines:2 colums:10
root lines:3 colums:10
awk的逻辑运算符
[[email protected] opt]# cat passwd | awk ‘{FS=":"} $3<10 {print $1 "\t" $3}‘
root:x:0:0:root:/root:/bin/bash
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
怎么第一行没有正确的显示出来呢?这是因为我们读入第一行的事后,那些变量$1,$2默认还是以空格键为分隔的,所以虽然我们定义了FS=“:“了,但是却仅能在第二行后才开始生效。那怎么办呢?我们可以预先设置awk变量!利用BEGIN这个关键字,这样做
[[email protected] opt]# cat passwd | awk ‘BEGIN {FS=":"} $3<10 {print $1 "\t" $3}‘
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
除了BEGIN之外,还有END呢!另外,如果要用awk来进行“计算功能”呢?
[[email protected] opt]# cat pay.txt|awk ‘NR==1{printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4,"total"}\
> NR>=2{total = $2+$3+$4\
> printf "%10s %10d %10d %10d %10.2f\n",$1,$2,$3,$4,total}‘
所有awk的动作,即在{}内的动作,如果有需要多个命令辅助时,可利用分号;分隔,或者直接以【enter】的按键来隔开每个命令,例如上面
逻辑运算中,如果是“等于”的情况,务必使用两个等号“==”
格式化输出时,在printf的格式设置当中,务必加上\n,才能进行分行
与bash,shell的变量不同,在awk中,变量可以直接使用,不需要加上$符号。