awk工具

awk工具和sed工具还有grep工具都相似,而awk工具都比前两者功能都要丰富的多。 awk工具强大足以可以写一本专门的书,所以这里就学习日常所需的知识点用于处理日常工作中需要的技巧。

截取文档中的某个段;

[root@Ask-02 演示3]# head -n2 test.txt |awk -F ':' '{print $1}' root bin

这里,-F选项是指定分隔符。如果不加-F选项,则会以空格或者tab为分隔符。print为打印的动作,用来答应某个字段,这里我选择打印的是第一段,用$1来表示,当然还有**$2**、$3这些,而**$0**比较特殊它代表的所有(即整行) 以下示例;

[root@Ask-02 演示3]# head -n2 test.txt |awk -F ':' '{print $0}' root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin

这里**-F**后面跟单引号,单引号里面是分隔符。print的动作需要用花括号“{}”括起来,否则会报错。print还可以打印自定义的内容,自定义的内容需要用双引号括起来。 比方说我们自定义用井号#来左右分隔符隔开段内容;

[root@Ask-02 演示3]# head -n2 test.txt |awk -F ':' '{print $1"#"$2"#"$3"#"}' root#x#0# bin#x#1#

匹配字符或者字符串;

[root@Ask-02 演示3]# awk '/oo/' test.txt root:x:0:0:root:/root:/bin/bash lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin mail:x:8:12:mail:/var/spool/mail:/sbin/nologin operator:x:11:0:operator:/root:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin setroubleshoot:x:990:985::/var/lib/setroubleshoot:/sbin/nologin

这跟sed工具的用法相似,能实现grep的功能但没有颜色的显示,这点自然没有grep方便,不过awk工具要比这两有着更强大的匹配 以下示例; [root@Ask-02 演示3]# awk -F ':' '$1 ~/oo/' test.txt root:x:0:0:root:/root:/bin/bash setroubleshoot:x:990:985::/var/lib/setroubleshoot:/sbin/nologin

可以看到它已第一段($1)去匹配(oo),不仅如此还可以多次匹配 以下示例; [root@Ask-02 演示3]# awk -F ':' '/root/ {print $1,$3} /test/ {print $1,$3}' test.txt root 0 test 3 operator 11

这里可以看到awk先匹配root,在匹配test,还可以只打印所匹配的段。

[root@Ask-02 演示3]# awk -F ':' '$3=="0"' test.txt root:x:0:0:root:/root:/bin/bash

awk工具可以用逻辑符号进行判断,比如==就是等于,也可以理解为精确匹配。另外还有**>、>=、<、<=等。在和数字比较时,若把比较的数字用双引号引起来,那么awk**不会认为是数字,而会认为是字符,不加双引号则会认为是数字。 以下示例;

[root@Ask-02 演示3]# awk -F ':' '$3>="500"' test.txt shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown halt:x:7:0:halt:/sbin:/sbin/halt mail:x:8:12:mail:/var/spool/mail:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin

这一示例中我本意是想把第三段数值大于500的匹配打印出来,但并没有成功,这是应为我加上了双引号,awk把所有的数字当作了字符,这是只要不加双引号即可;

[root@Ask-02 演示3]# awk -F ':' '$3>=500' test.txt systemd-bus-proxy:x:999:997:systemd Bus Proxy:/:/sbin/nologin polkitd:x:998:996:User for polkitd:/:/sbin/nologin chrony:x:997:995::/var/lib/chrony:/sbin/nologin

除了针对某一段的字符进行逻辑比较外,还可以在两段之间进行逻辑比较;

[root@Ask-02 演示3]# awk -F ':' '$3<$4' test.txt adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin test:x:3:6:kajds:aksjdk:lkj/asd mail:x:8:12:mail:/var/spool/mail:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

使用**&&||**,分别表示“并且”和“或者” 以下示例;

[root@Ask-02 演示3]# awk -F ':' '$3<"$5" && $3<"$7"' test.txt
或者 [root@Ask-02 演示3]# awk -F ':' '$3>1000 || $3=="/bin/bash"' test.txt nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin

awk的内置变量 awk的常用变量有OFSNFNROFS和**-F**选项有类似的功能,也是用来定义分隔符的,但是他是在输出的时候定义,NF表示用分隔符分隔后一共有多少段,NR表示行号。

OFS示例;

[root@Ask-02 演示3]# head -5 test.txt |awk -F ':' '{OFS="#"}{print $1,$3,$4}' root#0#0 bin#1#1 daemon#2#2 adm#3#4 lp#4#7

以及更高级一些的用法;

[root@Ask-02 演示3]# awk -F ':' '{OFS="#"} {if ($3>1000) {print $1,$2,$3,$4}}' test.txt nfsnobody#x#65534#65534

NF示例;

[root@Ask-02 演示3]# head -n3 test.txt | awk -F ':' '{print NF}' //NF表示多少段 7 7 7

NR示例;

[root@Ask-02 演示3]# head -n3 test.txt | awk -F ':' '{print NR}' 1 2 3

还可以使用NR做为判断条件;

[root@Ask-02 演示3]# awk 'NR>40' test.txt setroubleshoot:x:990:985::/var/lib/setroubleshoot:/sbin/nologin gdm:x:42:42::/var/lib/gdm:/sbin/nologin gnome-initial-setup:x:989:984::/run/gnome-initial-setup/:/sbin/nologin ask:x:1000:1000:Ask:/home/ask:/bin/bash

也可以配合段匹配使用;

[root@Ask-02 演示3]# awk -F ':' 'NR<20 && $1 ~ /root/' test.txt root:x:0:0:root:/root:/bin/bash

awk中的数学运算

awk更改段值;

[root@Ask-02 演示3]# head -n 3 test.txt |awk -F ':' '$1="root"' root x 0 0 root /root /bin/bash root x 1 1 bin /bin /sbin/nologin root x 2 2 daemon /sbin /sbin/nologin

awk可以对各个段的值进行数学运算;

[root@Ask-02 演示3]# head -n2 test.txt root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin [root@Ask-02 演示3]# head -n2 test.txt |awk -F ':' '{$7=$3+$4; print $0}' root x 0 0 root /root 0 bin x 1 1 bin /bin 2

awk计算某个段的总格;

[root@Ask-02 演示3]# awk -F ':' '{(tot=tot+$3)}; END {print tot}' test.txt 79232

这里END是awk特有的语法,表示所有的行都已经执行。