运维三剑客之awk

  AWK的叫法来源于其三位创始人姓氏首字母,需要注意的是,我们现在使用的awk其实多为gawk(基于GNU项目的awk的实现方式,除了正常的awk功能还额外提供了一些扩展):

  AWK默认以换行符为标记对文本进行逐行处理,那么尤其那些每行格式相同的文本文件,用AWK来格式化数据输出的时候会非常方便。所以人们常说AWK擅长处理列。

  • 基本语法
awk [OPTION] 'Pattern{Action}' file

  其中Pattern表示AWK在数据中查找的内容,而Action是在找到匹配内容时所执行的一系列命令。我们通过举例来说明他们的用法。

最常用的OPTION举例

  以下是比较实用的一些参数,其他使用频率低的参数感兴趣的话可以看看man手册。

参数 功能
-F 自定义分隔符,太实用了
-f 指定awk脚本,可以提前将'Pattern{Action}'写好

最常用的Action举例

  • 单纯打印文件内容
[root@localhost ~]# awk '{print}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
...
  • 提取第1列
[root@localhost ~]# awk -F : '{print $1}' /etc/passwd
root
bin
daemon
adm
lp
sync
...

  输出结果是按冒号(默认是空格或制表符作为分隔符,而且会自动将连续空格理解为1个分割单位)进行分割。此处还使用了内置变量:$1表示第一列,$0表示所有列(整行),$NF表示最后一列,$(NF-1)就可以表示倒数第二列。

  • 实现提取结果拼接自定义字符串
[root@localhost ~]# awk -F : '{ print "user:"$1}' /etc/passwd
user:root
user:bin
user:daemon
user:adm
user:lp
user:sync
...
  • 打印结果时调用内置函数

  这里我们介绍几个最常用的函数,大小写转换toupper/tolower,按长度(从m到n)进行截取substr(s,m,n) :

[root@localhost ~]# awk -F : '{ print toupper($1)}' /etc/passwd
ROOT
BIN
DAEMON
ADM
LP
SYNC
...
[root@localhost ~]# awk -F : '{ print substr($1,1,2)}' /etc/passwd
ro
bi
da
ad
lp
sy
...

常用的Pattern举例

  • BEGIN模式

  该模式指定了处理文本之前需要执行的操作,常用来初始化变量:

[root@localhost ~]# awk -F : 'BEGIN{printf "NAME PASSWD\n"} {print $1,$2}' /etc/passwd
NAME PASSWD
root x
bin x
daemon x
adm x
lp x
sync x
...
  • END模式

  模式指定了处理完所有行之后所需要执行的操作:

[root@localhost ~]# awk -F : 'BEGIN{print "NAME PASSWD";count=0} {print $1;count = count + 1} END{printf "行数总计: %d\n",count}' /etc/passwd
NAME PASSWD
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator
games
ftp
nobody
systemd-network
dbus
polkitd
sshd
postfix
dhcpd
apache
tss
chrony
geoclue
行数总计: 23
[root@localhost ~]# 
  • 匹配模式

  通过正则表达式(awk支持的ERES扩展的正则表达式)实现过滤,如匹配含有字符串bash的行:

[root@localhost ~]# awk '/bash/ {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# 
  • 条件模式

  通过设置条件实现过滤,如匹配奇数行:

[root@localhost ~]# awk 'NR % 2 == 1 {print "line_num:"NR,$0}' /etc/passwd
line_num:1 root:x:0:0:root:/root:/bin/bash
line_num:3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
line_num:5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
...

其他

  再强大的命令,只有和其他命令结合,才能变得更加实用。awk可以将输出作为其他命令的参数,使用管道即可:

[root@localhost ~]# awk 'BEGIN { print "hello" | "tr [a-z] [A-Z]" }'
HELLO
[root@localhost ~]# 

发表评论

评论列表,共 0 条评论

    暂无评论