awk匹配模式
正则表达式
匹配记录(整行)
匹配 /etc/passwd 文件中以 root 开头的
$ awk '/^root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
            
$ awk '$0 ~/^root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
匹配字段	匹配操作符(~|!~)
匹配 /etc/passwd 文件中第一列以 root 开头的
$ awk '$1~/^root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
匹配 /etc/passwd 文件中最后一列不是以 bash 结尾的
$ awk '$NF !~ /bash$/' /etc/passwd|head -5
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
^ 和 ~ 用法示例
^ 在awk中表示以 ... 开头的列,在 sed 、grep 中表示以 ... 开头的行
^ 用法示例
文件 t.txt 内容如下
1 101,hehe,CEO
2 102,haha,CTO
3 103,xixi,COO
4 105,yy,CFO
5 106,xx,CIO
6 110,jjxx,COCO
示例:打印文件中以1开头的行
$ awk '/^1/{print}' t.txt 
1 101,hehe,CEO
~ 用法示例
文件 t1.txt 内容如下
zhang  san  1234567    
li     si   6666666
wang   wu   6666667  
zhao   liu  67676798   
hao    qi   11112222   
zhu    ba   00000001
显示所有ID号码最后一位是2或7的人的全名
$ awk '$3~/[27]$/{print $1,$2}' t1.txt
zhang san
wang wu
hao qi
显示文件中第三列以1开头的行
$ awk '$3~/^1/{print}' t1.txt 
zhang  san  1234567    
hao    qi   11112222   
显示zhang的姓氏和ID号码
$ awk '$1~/zhang/{print $1,$3}' t1.txt 
zhang 1234567
条件表达式
关系运算符
| 运算符 | 含义 | 
|---|---|
< | 小于 | 
<= | 小于等于 | 
== | 等于 | 
!= | 不等于 | 
> | 大于 | 
>= | 大于等于 | 
~ | 模糊匹配 | 
!~ | 模糊匹配取反 | 
示例
文件 t.txt 内容如下
1 101,hehe,CEO
2 102,haha,CTO
3 103,xixi,COO
4 105,yy,CFO
5 106,xx,CIO
6 110,jjxx,COCO
示例1:打印第一列大于3的行
$ awk '{if($1>3)print}' t.txt 
4 105,yy,CFO
5 106,xx,CIO
6 110,jjxx,COCO
示例2:显示磁盘使用率大于10%的磁盘分区和挂载点
$ df -h|awk -F'[% ]+' 'NR>1 && $5>10{print $1,$5"%",$NF}'
/dev/vda1 63% /
/dev/vdb 22% /data
示例3:计算内存使用率
查看内存使用情况
$ free -m
              total        used        free      shared  buff/cache   available
Mem:           7822         552        2055          14        5215        6957
Swap:             0           0           0
计算内存使用率
free -m|awk 'NR==2{print ($2-$NF)/$2*100"%"}'
11.0586%
示例4:同时计算内存使用率和空闲率
计算内存使用率和空闲率
$ free -m | awk 'NR==2{print ($2-$NF)/$2*100"%",$NF/$2*100"%"}'
11.0969% 88.9031%
awk的一个坑
awk会把数字当成字符处理
查看磁盘使用率
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        3.9G     0  3.9G   0% /dev
tmpfs           3.9G     0  3.9G   0% /dev/shm
tmpfs           3.9G   15M  3.9G   1% /run
tmpfs           3.9G     0  3.9G   0% /sys/fs/cgroup
/dev/vda1        99G   59G   36G  63% /
/dev/vdb        197G   40G  147G  22% /data
tmpfs           783M     0  783M   0% /run/user/0
tmpfs           783M     0  783M   0% /run/user/19708
tmpfs           783M     0  783M   0% /run/user/19821
tmpfs           783M     0  783M   0% /run/user/19727
打印第二行第5列小于9的列,可以结果不正确,63、22都是大于9的,打印的结果并非 小于9
$ df -h|awk 'NR>1 && $5<9{print $1,$5,$NF}'
devtmpfs 0% /dev
tmpfs 0% /dev/shm
tmpfs 1% /run
tmpfs 0% /sys/fs/cgroup
/dev/vda1 63% /
/dev/vdb 22% /data
tmpfs 0% /run/user/0
tmpfs 0% /run/user/19708
tmpfs 0% /run/user/19821
tmpfs 0% /run/user/19727
因为awk会把数字当成字符处理,比如 sort
如下所示,sort 会把数字当成字符处理,并没有把数字从大到小排序
$ seq 15|sort
1
10
11
12
13
14
15
2
3
4
5
6
7
8
9
解决awk把数字当成字符处理问题的方法
- 
方法1 用指定分隔符的方式把数字和
%分隔开# 正确输出
$ df -h|awk -F'[% ]+' '$5<9{print $1,$5,$NF}'
devtmpfs 0 /dev
tmpfs 0 /dev/shm
tmpfs 1 /run
tmpfs 0 /sys/fs/cgroup
tmpfs 0 /run/user/0
tmpfs 0 /run/user/19708
tmpfs 0 /run/user/19821
tmpfs 0 /run/user/19727
# 不正确输出
$ df -h|awk '$5<9{print $1,$5,$NF}'
devtmpfs 0% /dev
tmpfs 0% /dev/shm
tmpfs 1% /run
tmpfs 0% /sys/fs/cgroup
/dev/vda1 63% /
/dev/vdb 22% /data
tmpfs 0% /run/user/0
tmpfs 0% /run/user/19708
tmpfs 0% /run/user/19821
tmpfs 0% /run/user/19727 - 
方法2 让awk知道进行数字比较,某一列加0
# 正确输出
$ df -h|awk 'NR>1 && $5+0<9{print $1,$5,$NF}'
devtmpfs 0% /dev
tmpfs 0% /dev/shm
tmpfs 1% /run
tmpfs 0% /sys/fs/cgroup
tmpfs 0% /run/user/0
tmpfs 0% /run/user/19708
tmpfs 0% /run/user/19821
tmpfs 0% /run/user/19727
# 不正确输出
$ df -h|awk 'NR>1 && $5<9{print $1,$5,$NF}'
devtmpfs 0% /dev
tmpfs 0% /dev/shm
tmpfs 1% /run
tmpfs 0% /sys/fs/cgroup
/dev/vda1 63% /
/dev/vdb 22% /data
tmpfs 0% /run/user/0
tmpfs 0% /run/user/19708
tmpfs 0% /run/user/19821
tmpfs 0% /run/user/19727 
运算表达式
示例1:打印 /etc/passwd 第三列与10相乘大于5000的内容
$ awk -F: '$3 * 10 > 5000' /etc/passwd
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
mysql:x:1000:1000::/home/mysql:/sbin/nologin
示例2:打印 /etc/passwd 第三列与10相乘大于500的内容,并打印第一列和第三列
$ awk -F: 'BEGIN{OFS="--"} { if($3*10>5000) {print $1,$3} } END {print "打印ok"}' /etc/passwd
polkitd--999
chrony--998
mysql--1000
打印ok
示例3:加、减、乘、除、取模、幂运算
文件 test.txt 内容如下
a 1 2 3 4 5
b 1 2 3 4 5
a 5 6 7 8 9
加法计算
$ awk '/a/{print $2+10}' test.txt 
11
15
减法计算
$ awk '/a/{print $2-10}' test.txt 
-9
-5
乘法计算
$ awk '/a/{print $2*10}' test.txt 
10
50
除法计算
$ awk '/a/{print $2/10}' test.txt 
0.1
0.5
取模计算
$ awk '/a/{print $2%10}' test.txt 
1
5
幂计算
$ awk '/a/{print $2**10}' test.txt 
1
9765625
逻辑操作符和复合模式
逻辑操作符
| 符号 | 含义 | 
|---|---|
&& | 逻辑与 | 
| ` | |
! | 逻辑非 | 
示例1:打印 /etc/passwd 文件中用户名为 root 并且打印 uid 小于15的行
# 文件中第三列是UID
$ awk -F: '$1~/root/ && $3<=1' /etc/passwd 
root:x:0:0:root:/root:/bin/bash
示例2:打印用户名为 root 或第三列大于500的行
$ awk -F: '$1~/root/ || $3>=500' /etc/passwd
root:x:0:0:root:/root:/bin/bash
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
chrony:x:998:996::/var/lib/chrony:/sbin/nologin
mysql:x:1000:1000::/home/mysql:/bin/false
三元运算符
三元运算符表达式
三元运算符的形式1:[ 结果 = 条件 ? 结果1 :结果2 ]
三元运算符的形式2:[ 条件 ? 表达式1 : 表达式2 ]
示例:
文件 t.txt 内容如下
student1 98
student2 99
student3 93
student4 78
student5 85
根据学生成绩判断学生成绩是否为优秀,这里规定分数大于90是优秀,低于90非优秀
- 
非三元运算写法
$ awk '{if($2>90){print $1,"优秀"}else{print $1,"不优秀"}}' t.txt
student1 优秀
student2 优秀
student3 优秀
student4 不优秀
student5 不优秀 - 
三元运算写法
- 
写法1
结果 = 条件 ? 结果1:结果2$ awk '{res=$2>90?"优秀":"不优秀";print $1,res}' t.txt
student1 优秀
student2 优秀
student3 优秀
student4 不优秀
student5 不优秀
# 上述awk写法中的print也可以单独写在一个大括号中
awk '{res=$2>90?"优秀":"不优秀"}{print $1,res}' t.txt - 
写法2
条件 ? 表达式1 :表达式2# a表示符合条件的,b表示不符合条件的,大于90分的有3个,低于90分的有2个
$ awk '{$2>90?a++:b++}END{print a,b}' t.txt
3 2 
 - 
 

