相较于 sed 常常作用于一整个行的处理, awk 则比较倾向于一行当中分成数个『字段』来处理。 因此, awk 相当的适合处理小型的数据处理呢! awk 可以处理后续接的档案,也可以读取来自前个指令的 standard output 。
awk通常运作得模式
[root@linux ~]# awk '条件类型 1{动作 1} 条件类型 2{动作 2} ...' filename
例一:取出账号与登入者得 IP ,且账号与IP之间以[tab]隔开
[root@linux ~]# last | awk '{print $1 " " $3}' dmtsai 192.168.1.12 root Mon reboot boot dmtsai 192.168.1.12
说明:
1.每一行的每个字段都是有变量名称的,那就是$1,$2... 等变量名称。例如dmtsai是$1,192.168.1.12是第三栏,所以他就是$3啦。
2.还有个$0,$0代表一整行的意思。
awk处理流程
1. 读入第一行,并将第一行的资料填入 $0, $1, $2.... 等变数当中;
2. 依据 "条件类型" 的限制,判断是否需要进行后面的 "动作";
3. 做完所有的动作与条件类型;
4. 若还有后续的『行』的数据,则重复上面 1~3 的步骤,直到所有的数据都读完为止。
awk内建变量
变量名称
|
代表意义
|
NF
|
每一行 ($0) 拥有的字段总数
|
NR
|
目前 awk 所处理的是『第几行』数据
|
FS
|
目前的分隔字符,预设是空格键
|
例二:列出每一行得账号,并且列出目前处理的行数,并且说明,该行有多少字段。
[root@linux ~]# last | awk '{print $1 " lines: " NR " columes: " NF}' dmtsai lines: 1 columes: 10 root lines: 2 columes: 9 reboot lines: 3 columes: 9 dmtsai lines: 4 columes: 10
条件类型
awk 的逻辑运算字符
运算单元
|
代表意义
|
>
|
大于
|
<
|
小于 |
>=
|
大于或等于
|
<=
|
小于或等于
|
==
|
等于
|
!= |
不等于
|
例三:在/etc/passwd当中是以冒号":"来作为字段的分隔,那假设我要查阅,第三栏小于30以下得数据,并且仅列出账号与第三栏。
linux-xuzz:~/test # cat /etc/passwd | awk '{FS=":"} $3<30 {print $1 " " $3}' bin 1 daemon 2 games 12 。。。。。。
这样就可以显示出来了,但是有一个问题,第一行为什么没有正确得显示出来?
这是因为我们读入第一行的时候, 那些变数 $1, $2... 预设还是以空格键为分隔的,所以虽然我们定义了 FS=":" 了, 但是却仅能在第二行后才开始生效。
利用BEGIN关键词,可以预先设定awk的内建变量!
linux-xuzz:~/test # cat /etc/passwd | awk 'BEGIN {FS=":"} $3<30 {print $1 " " $3}' at 25 bin 1 daemon 2 games 12
怎么样,第一行得at账户就显示出来啦,除了BEGIN之外,还有END关键字
例四:假设我有一个薪资数据表,如何帮我计算每个人的总额呢?而且我还想要格式化输出喔!
[root@linux ~]# cat pay.txt | > awk 'NR==1{printf "%10s %10s %10s %10s %10s ",$1,$2,$3,$4,"Total" } NR>=2{total = $2 + $3 + $4 printf "%10s %10d %10d %10d %10.2f ", $1, $2, $3, $4, total}' Name 1st 2nd 3th Total VBird 23000 24000 25000 72000.00 DMTsai 21000 20000 23000 64000.00 Bird2 43000 42000 41000 126000.00
说明:
1.多个指令辅助时,可利用分号『 ;』间隔, 或者 直接以 [Enter] 按键来隔开每个指令。
2.在awk的动作里面,可以如同shell一样使用各式各样不同得命令。
3.另外一种使用if(条件)的方式:
[root@linux ~]# cat pay.txt | > awk '{if(NR==1) printf "%10s %10s %10s %10s %10s ",$1,$2,$3,$4,"Total"} NR>=2{total = $2 + $3 + $4 printf "%10s %10d %10d %10d %10.2f ", $1, $2, $3, $4, total}'