四,awk格式化
之前的文章举过很多例子,我们也体验到了awk的格式化能力,但是我们的体验并不全面,所以,现在,我们来更加深刻的了解一下awk的格式化能力,在前文的举例中,我们在使用awk时,通常使用print 对文本进行输出,但是动作print 只能实现简单的文本输出功能,并不能对文本格式进行改变,如果想要改变文本的格式,则需要awk中的另一个动作,此动作与print很像,它就是printf,没错,看到printf,你肯定会想到printf命令,或者想到了C语言中的printf()函数,如果你想到了这些,那么使用printf对你来说应该不在话下了,如果你并没有接触过printf命令或者printf()函数,没有关系,你可以先阅读如下连接对应的文章,即可学会printf命令的使用方法
利用awk中的printf动作,即可对文本进行格式化输出,printf动作的用法与printf命令的用法非常相似,只是有略微的不同而已,不过,我们还是从最简单的示例开始看起,首先对比一下print动作与printf动作的区别,示例如下
[root@node1 ~]# awk '{print $1}' test1 abc 8ua [root@node1 ~]# awk '{printf $1}' test1 abc8ua[root@node1 ~]#
注意:使用print输出时如果不加参数例如本次的$1则默认是输出所有即$0
使用printf必须加类似参数$1否则报错
awk '{printf}' test1 awk: cmd. line:1: (FILENAME=test1 FNR=1) fatal: printf: no arguments
聪明如你一定想到了,既然printf动作的用法与printf命令一样,那么,printf动作有没有printf命令中所谓的"格式替换符"呢?
必须有啊,"格式替换符"是什么我们就不再赘述了,因为在printf命令详解中已经详细的解释过它,那么我们来使用"格式替换符"来指定一下$1的格式,示例如下。
[root@node1 ~]# awk '{printf "%s\n",$1}' test1 abc 8ua
如果只看上图中红线标注的部分,你肯定会认为,这就是printf命令的用法,只是printf动作与printf命令在语法上唯一的不同点就是,在使用printf动作时,指定的"格式"与列($1)之间需要用"逗号"隔开,而使用printf命令时,指定的格式与传入的文本不需要使用"逗号"隔开
[root@node1 ~]# awk '{printf "%s\n",$1}' test1 abc 8ua [root@node1 ~]# printf "%s\n" testString testString [root@node1 ~]#
其实,它们还有一些其他的不同之处,我们在使用printf命令时,当指定的格式中只有一个"格式替换符",但是传入了多个参数时,那么这多个参数可以重复的使用这一个格式替换符,示例如下
[root@node1 ~]# printf "%s\n" 1 2 3 4 5 1 2 3 4 5
但是在awk中,我们则不能这样使用,在awk中,格式替换符的数量必须与传入的参数的数量相同,换句话说,格式替换符必须与需要格式化的参数一一对应,示例如下
[root@node1 ~]# awk 'BEGIN{printf "%s\n", 1,2,3,4,5}' 1 [root@node1 ~]# awk 'BEGIN{printf "%s\n%s\n%s\n%s\n%s\n", 1,2,3,4,5}' 1 2 3 4 5
好了,这就是awk中printf动作在使用时的一些注意点。
我们来总结一下,在awk中使用printf动作时,需要注意以下3点。
1)使用printf动作输出的文本不会换行,如果需要换行,可以在对应的"格式替换符"后加入"\n"进行转义。
2)使用printf动作时,"指定的格式" 与 "被格式化的文本" 之间,需要用"逗号"隔开。
3)使用printf动作时,"格式"中的"格式替换符"必须与 "被格式化的文本" 一一对应。
我们可以利用格式替换符对文本中的每一列进行格式化,示例如下。
[root@node1 ~]# awk '{printf "第一列:%s 第二列:%s\n",$1,$2}' test1 第一列:abc 第二列:123 第一列:8ua 第二列:456
我们可以利用awk的内置变量FS,指定输入字段分隔符,然后再利用printf动作,进行格式化,示例如下。
[root@node1 ~]# cat test abc#123#iuy#ddd 8ua#456#auv#ppp#7y7 [root@node1 ~]# awk -v FS="#" '{printf "第一列:%s\t 第二列:%s\n",$1,$2}' test 第一列:abc 第二列:123 第一列:8ua 第二列:456
上例完美的体现了awk的格式化能力,因为awk本身负责文本切割,printf动作负责格式化文本,双剑合璧了。
继续扩展一下,可以利用awk的begin模式,结合printf动作,输出一个像样的表格,下图中用到的"修饰符"此处不再赘述,如果不明白,参考printf命令详解。
[root@node1 ~]# awk -v FS=":" 'BEGIN{printf "%-10s\t %s\n","用户名称","用户ID"} {printf "%-10s\t %s\n",$1,$3}' /etc/passwd 用户名称 用户ID root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 operator 11 games 12 ftp 14 nobody 99 systemd-network 192 dbus 81 polkitd 999 sshd 74 postfix 89 chrony 998 zabbix 997 rpc 32 rpcuser 29 nfsnobody 65534 ntp 38 libstoragemgmt 996 ceph 167 apache 48 jack 1000 owen 1001 tss 59 liuym 1002 tcpdump 72
其实话说回来,只要能够灵活的使用printf命令,再结合printf动作使用时的3个注意点,即可快速灵活的掌控它,好了,关于awk的格式化能力,就暂时总结到这里。