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
-