awk高级

awk高级

1. 工作流程

我们要注意的一点就是awk是一行一行处理的,并不是一下子就把一整列给取出来了。

打印列:

[root@dy1 ~]# cat test.txt
00 11 22
33 44 55
66 77 88

//$0代表一整行
[root@dy1 ~]# awk '{print $0}' test.txt
00 11 22
33 44 55
66 77 88

//NR的意思是行号
[root@dy1 ~]# awk '{print NR,$0}' test.txt
1 00 11 22
2 33 44 55
3 66 77 88

//打印第一列和第三列
[root@dy1 ~]# awk '{print $1,$3}' test.txt
00 22
33 55
66 88

//打印每一行有多少列
[root@dy1 ~]# awk '{print NF}' test.txt
3
3
3

//打印最后一列
[root@dy1 ~]# awk '{print $NF}' test.txt
22
55
88

//打印最后一列的数值减去1
[root@dy1 ~]# awk '{print $NF-1}' test.txt
21
54
87

//打印倒数第二列
[root@dy1 ~]# awk '{print $(NF-1)}' test.txt
11
44
77
[root@dy1 ~]# cat test.txt
00:11 22
33:44 55
66:77 88

//以:分隔,打印第二列
[root@dy1 ~]# awk -F":" '{print $2}' test.txt
11 22
44 55
77 88

//以空格分隔,打印第二列
[root@dy1 ~]# awk -F" " '{print $2}' test.txt
22
55
88

//以空格或者以冒号为分隔符打印
[root@dy1 ~]# awk -F"[ :]" '{print $1}' test.txt
00
33
66

分隔符:

//打印不规则的文本
[root@dy1 ~]# cat test.txt
00::11  22
33::44     55
66::77           88

//分隔符可以有多个,而且可以连接出现多次
[root@dy1 ~]# awk -F"[ :]+" '{print $1}' test.txt
00
33
66
[root@dy1 ~]# awk -F"[ :]+" '{print $NF}' test.txt
22
55
88
//FS相当于-F 指定什么为分隔符,使用-F实际就是修改FS
[root@dy1 ~]# cat test.txt
00::11  22
33::44     55
66::77           88
[root@dy1 ~]# awk 'BEGIN {FS="[ :]+"} {print $NF}' test.txt
22
55
88

[root@dy1 ~]# awk 'BEGIN {FS="[ :]+"} {print $1,$2}' test.txt
00 11
33 44
66 77

//默认打印时分隔符是以空格,可以通过OFS指定打印时的分隔符
[root@dy1 ~]# awk 'BEGIN {FS="[ :]+";OFS="@@"} {print $1,$2}' test.txt
00@@11
33@@44
66@@77
//小练习,分别用三剑客取出IP地址
[root@dy1 ~]# ip addr show eth0 | awk 'NR==3{print $2}' | sed -r 's@(^.*)\/24@\1@'
192.168.80.146
[root@dy1 ~]# ip addr show eth0 | awk 'NR==3{print $2}' | egrep -o '^.*/' | tr -d /
192.168.80.146
[root@dy1 ~]# ip addr show eth0 | awk 'NR==3{print $2}' | awk -F"/" '{print $1}'
192.168.80.146

NR与FNR

[root@dy1 ~]# cat test.txt 
00::11  22
33::44     55
66::77           88
[root@dy1 ~]# cat /etc/issue
\S
Kernel \r on an \m

//用NR如果对两个文件操作的话,行号会延续
[root@dy1 ~]# awk 'BEGIN {FS="[ :]+";OFS="@@"} {print NR":"$1,$2}' test.txt /etc/issue
1:00@@11
2:33@@44
3:66@@77
4:\S@@
5:Kernel@@\r
6:@@

////用FNR如果对两个文件操作的话,行号不会延续
[root@dy1 ~]# awk 'BEGIN {FS="[ :]+";OFS="@@"} {print FNR":"$1,$2}' test.txt /etc/issue
1:00@@11
2:33@@44
3:66@@77
1:\S@@
2:Kernel@@\r
3:@@

打印行

[root@dy1 ~]# cat test.txt 
00::11  22
33::44     55
66::77           88

//打印第二行
[root@dy1 ~]# awk 'NR==2{print $0}' test.txt
33::44     55
[root@dy1 ~]# awk 'NR==2{print $1}' test.txt
33::44
[root@dy1 ~]# awk -F"[: ]+" 'NR==2{print $1}' test.txt
33

//打印大于第1号,小于第3行的行的第一列,其实也就是第二行的第一列。
[root@dy1 ~]# awk -F"[: ]+" 'NR>1&&NR<3{print $1}' test.txt
33
//练习,打印用户的name和uid
[root@dy1 ~]# awk -F: '{print "name:" $1 "\t uid:" $3}' /etc/passwd | head -5
name:root	 uid:0
name:bin	 uid:1
name:daemon	 uid:2
name:adm	 uid:3
name:lp	 uid:4

//通过print不美观,通过printf会美观一些
[root@dy1 ~]# awk -F: '{printf "%-15s %-10s %-15s\n",$1,$2,$3}' /etc/passwd | head -5
root            x          0              
bin             x          1              
daemon          x          2              
adm             x          3              
lp              x          4         
awk -F: '{printf "%-15s %-10s %-15s\n","name:"$1,"this is:"$2,"uid:"$3}' /etc/passwd | head -5
name:root       this is:x  uid:0          
name:bin        this is:x  uid:1          
name:daemon     this is:x  uid:2          
name:adm        this is:x  uid:3          
name:lp         this is:x  uid:4          
  • %s 字符类型
  • %d数值类型
  • 占15个字符,-表示左对齐,尾部是右对齐
  • printf 默认不会自动换行,需要加\n

2. GEGIN&END

[root@dy1 ~]# awk 'BEGIN {print "START"} {print "00"} END {print "END"}' /etc/hosts
START
00
00
END

仔细体会上面的例子,为什么00会显示两次呢?是因为/etc/hosts的文件有两行,文件有几行,这里面的00就会打印几次,主要还是因为awk的工作原理使然,其工作原理就是取一行处理一行,文件当中一共有两行内容,这里面的00就会打印两次。

那么BEGIN和END里面的内容只会打印一次呢?是因为BEGIN和END并不会参加到处理动作里面去,所以只打印一次,处理前打印一次,处理后打印一次。

image-20200422084137330

3. 模式动作

正则表达式:

#匹配记录(整行)
[root@dy1 ~]# awk '/^root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@dy1 ~]# awk '$0 ~ /^root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash

匹配字段,匹配操作符

[root@dy1 ~]# awk '$1~/^root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@dy1 ~]# awk '$1 !~ /bash$/' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

比较表达式:

[root@dy1 ~]# awk -F: '$3==0' /etc/passwd
root:x:0:0:root:/root:/bin/bash

[root@dy1 ~]# awk -F: '$3<10' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin

[root@dy1 ~]# awk -F: '$7 == "/bin/bash"' /etc/passwd
root:x:0:0:root:/root:/bin/bash
zhanghe:x:1000:1000::/home/zhanghe:/bin/bash

//磁盘使用率大于多少则打印可用的值
[root@dy1 ~]# df | awk '/\/$/'| awk '$3>100000 {print $4}' 
44781576

条件表达式:

[root@dy1 ~]# awk -F: '$3>300 {print $0}' /etc/passwd
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
nginx:x:998:996:nginx user:/var/cache/nginx:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
zhanghe:x:1000:1000::/home/zhanghe:/bin/bash

[root@dy1 ~]# awk -F: '{if($3>300) print $0}' /etc/passwd
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
nginx:x:998:996:nginx user:/var/cache/nginx:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
zhanghe:x:1000:1000::/home/zhanghe:/bin/bash

[root@dy1 ~]# awk -F: '{if($3>5555) {print $3} else {print $1}}' /etc/passwd | head -5
root
bin
daemon
adm
lp

运算:

[root@dy1 ~]# awk -F: '$3 * 10 > 50000' /etc/passwd
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin

4. if

[root@dy1 ~]# df
Filesystem              1K-blocks    Used Available Use% Mounted on
/dev/mapper/centos-root  47023684 2242952  44780732   5% /
devtmpfs                  1001880       0   1001880   0% /dev
tmpfs                     1014044       0   1014044   0% /dev/shm
tmpfs                     1014044    9776   1004268   1% /run
tmpfs                     1014044       0   1014044   0% /sys/fs/cgroup
/dev/sda1                 1038336  135368    902968  14% /boot
tmpfs                      202812       0    202812   0% /run/user/0

//当用量超过9000时,就打印可用的空间
[root@dy1 ~]# df | awk '/\/run/{if ($3>9000) print "可用空间还有:"$4}'
可用空间还有:1004268

上述这个例子其实十分简单,取出有/run的行,如果第三列大于9000,就打印第四列。

posted @ 2020-04-23 18:51  张贺贺呀  阅读(181)  评论(0编辑  收藏  举报