awk匹配模式
1.正则表达式
1.1 匹配记录(整行)
匹配 /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
1.2 匹配字段 匹配操作符(|!)
匹配 /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中表示以 ...
开头的行
^用法示例
文件内容如下
$ cat 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
~用法示例
文件内容如下
$ cat t1.txt
zhang san 1234567 :550:100:175
li si 88883336 :155:90:201
wang wu 66666666 :250:60:50
zhao liu 67676798 :150:80:75
hao qi 11112222 :250:100:175
zhu ba 000098763 :50:95:135
显示所有ID号码最后一位是2或7的人的全名
$ awk '$3~/[27]$/{print $1,$2}' t1.txt
zhang san
hao qi
显示文件中第三列以1开头的行
$ awk '$3~/^1/{print}' t1.txt
zhang san
hao qi
显示zhang的姓氏和ID号码
$ awk '$1~/zhang/{print $1,$3}' t1.txt
zhang 1234567
显示zhang的捐款,每个值都以 $
开头,如 $250$100$175
-
方法一
$ awk -vFS='[ :]+' -vOFS=$ '$1~/zhang/{print "$"$4,$5,$NF}' t1.txt
$550$100$175 -
方法二
:::tip说明
awk替换函数gsub gsub 全局替换 awk内置命令(函数)
使用方法
gsub(//,"",$n) n表示数字
gsub(/找谁/,"替换为什么",替换哪一列):::
$ awk '$1~/zhang/{gsub(/:/,"$",$NF);print $1,$NF}' t1.txt
zhang $550$100$175
2.条件表达式
2.1 关系运算符
运算符 | 含义 |
---|---|
< | 小于 |
<= | 小于等于 |
== | 等于 |
!= | 不等于 |
> | 大于 |
>= | 大于等于 |
~ | 模糊匹配 |
!~ | 模糊匹配取反 |
2.2 示例
文件内容如下
$ cat 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
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 17G 2.4G 15G 14% /
devtmpfs 224M 0 224M 0% /dev
tmpfs 236M 0 236M 0% /dev/shm
tmpfs 236M 9.6M 226M 5% /run
tmpfs 236M 0 236M 0% /sys/fs/cgroup
/dev/sda1 1014M 132M 883M 14% /boot
tmpfs 48M 0 48M 0% /run/user/0
$ df -h|awk -F'[% ]+' 'NR>1 && $5>10{print $1,$5"%",$NF}'
/dev/mapper/centos-root 14% /
/dev/sda1 14% /boot
示例3:计算内存使用率
-
centos6
centOS6查看内存使用
$ free -m
total used free shared buffers cached
Mem: 474 171 303 0 30 44
-/+ buffers/cache: 95 378
Swap: 1023 0 1023centOS6计算内存使用率
$ free -m|awk 'NR==3{print $3/($3+$4)*100"%"}'
20.296% -
centos7
Centos7查看内存使用
$ free -m
total used free shared buff/cache available
Mem: 470 90 243 5 136 330
Swap: 2047 0 2047Centos7计算内存使用率
$ free -m|awk 'NR==2{print ($2-$NF)/$2*100"%"}'
30%
示例4:同时计算内存使用率和空闲率
-
centos6
centos6计算内存使用率和空闲率
$ free -m|awk 'NR==3{print $3/($3+$4)*100"%",$NF/($3+$NF)*100"%"}'
20.4641% 79.5359% -
centos7
centos7计算内存使用率和空闲率
$ free -m|awk 'NR==2{print ($2-$NF)/$2*100"%",$NF/$2*100"%"}'
30% 70%
2.3 awk的一个坑
:::caution注意
awk会把数字当成字符处理
:::
查看磁盘使用率
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 19G 2.4G 16G 14% /
tmpfs 238M 0 238M 0% /dev/shm
/dev/sda1 190M 35M 146M 19% /boot
打印第二行第5列小于9的列,结果不正确
$ df -h|awk 'NR>1 && $5<9{print $1,$5,$NF}'
/dev/sda3 14% /
tmpfs 0% /dev/shm
/dev/sda1 19% /boot
因为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}'
tmpfs 0 /dev/shm
# 不正确输出
$ df -h|awk '$5<9{print $1,$5,$NF}'
/dev/sda3 14% /
tmpfs 0% /dev/shm
/dev/sda1 19% /boot -
方法2 让awk知道进行数字比较,某一列加0
# 正确输出
$ df -h|awk 'NR>1 && $5+0<9{print $1,$5,$NF}'
tmpfs 0% /dev/shm
# 不正确输出
$ df -h|awk 'NR>1 && $5<9{print $1,$5,$NF}'
/dev/sda3 14% /
tmpfs 0% /dev/shm
/dev/sda1 19% /boot
3.运算表达式
示例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:加、减、乘、除、取模、幂运算
文件内容如下
$ cat 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
4.逻辑操作符和复合模式
4.1 逻辑操作符
符号 | 含义 |
---|---|
&& | 逻辑与 |
|| | 逻辑或 |
! | 逻辑非 |
示例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
4.2 三元运算符
三元运算符表达式
三元运算符的形式1:[ 结果 = 条件 ? 结果1 :结果2 ]
三元运算符的形式2:[ 条件 ? 表达式1 : 表达式2 ]
示例:
文件内容如下
$ cat 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
-
风骚走位!!!
文件内容
$ cat lessons.txt
634751 预排
568688 预排
386760 删除
619373 预排
428491 预排
487563 完成
603342 完成
436339 完成
结果:
删除 386760
完成 487563,603342,436339
预排 634751,568688,619373,428491
啥意思?
# 方法1
$ awk '{a[$2]=a[$2]?a[$2]","$1:a[$2]$1}END{for(i in a) print i,a[i]}' lessons.txt
删除 386760
完成 487563,603342,436339
预排 634751,568688,619373,428491
# 方法2
$ awk '{if(a[$2]){a[$2]=a[$2]","$1}else{a[$2]=a[$2]$1}}END{for(i in a) print i,a[i]}' lessons.txt
删除 386760
完成 487563,603342,436339
预排 634751,568688,619373,428491
啥意思?
$ awk '{a[$2]=a[$2]","$1}END{for(i in a) print i,a[i]}' lessons.txt
删除 ,386760
完成 ,487563,603342,436339
预排 ,634751,568688,619373,428491