awk匹配模式

一、正则表达式

1.1匹配记录(整行)

//匹配/etc/passwd文件中以root开头的
[root@7-test1 ~]# awk '/^root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash

[root@7-test1 ~]# awk '$0 ~/^root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash

1.2匹配字段 匹配操作符(~|!~)

//匹配/etc/passwd文件中第一列以root开头的
[root@7-test1 ~]# awk '$1~/^root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash

//匹配/etc/passwd文件中最后一列不是以bash结尾的
[root@7-test1 ~]# 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中表示以...开头的行

^用法示例

示例:打印文件中以1开头的行

//文件内容
[root@7-test1 awk]# 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

[root@7-test1 awk]# awk '/^1/{print}' t.txt 
1 101,hehe,CEO

~用法示例

//文件内容
[root@7-test1 awk]# 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号码最后一位是27的人的全名
[root@7-test1 awk]# awk '$3~/[27]$/{print $1,$2}' t1.txt
zhang san
hao qi


//显示文件中第三列以1开头的行
[root@7-test1 awk]# awk '$3~/^1/{print}' t1.txt 
zhang san
hao qi

//显示zhang的姓氏和ID号码
[root@7-test1 awk]# awk '$1~/zhang/{print $1,$3}' t1.txt 
zhang 1234567

//显示zhang的捐款,每个值都以$开头,如$250$100$175
方法一:
[root@7-test1 awk]# awk -vFS='[ :]+' -vOFS=$ '$1~/zhang/{print "$"$4,$5,$NF}' t1.txt 
$550$100$175

方法二:
awk替换函数gsub
gsub    全局替换    awk内置命令(函数)
使用方法
gsub(//,"",$n)  n表示数字
gsub(/找谁/,"替换为什么",替换哪一列)

[root@7-test1 awk]# awk '$1~/zhang/{gsub(/:/,"$",$NF);print $1,$NF}' t1.txt 
zhang $550$100$175

二、条件表达式

2.1关系运算符

运算符 含义
< 小于
<= 小于等于
== 等于
!= 不等于
> 大于
>= 大于等于
~ 模糊匹配
!~ 模糊匹配取反

2.2示例

示例1:打印第一列大于3的行

//文件内容
[root@7-test1 awk]# 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

[root@7-test1 awk]# awk '{if($1>3)print}' t.txt 
4 105,yy,CFO
5 106,xx,CIO
6 110,jjxx,COCO

示例2:显示磁盘使用率大于10%的磁盘分区和挂载点

[root@7-test1 awk]# 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

[root@7-test1 awk]# df -h|awk -F'[% ]+' 'NR>1 && $5>10{print $1,$5"%",$NF}'
/dev/mapper/centos-root 14% /
/dev/sda1 14% /boot

示例3:计算内存使用率

centOS6
//centOS6查看内存使用率
[root@test1 ~]# free -m
             total       used       free     shared    buffers     cached
Mem:           474        171        303          0         30         44
-/+ buffers/cache:         95        378
Swap:         1023          0       1023
//centOS6计算内存使用率
[root@test1 ~]# free -m|awk 'NR==3{print $3/($3+$4)*100"%"}'
20.296%

centOS7
//centOS7查看内存使用率
[root@7-test1 awk]# free -m
              total        used        free      shared  buff/cache   available
Mem:            470          90         243           5         136         330
Swap:          2047           0        2047
//centOS7计算内存使用率
[root@7-test1 awk]# free -m|awk 'NR==2{print ($2-$NF)/$2*100"%"}'
30%

示例4:同时计算内存使用率和空闲率

centOS6
//centOS6计算内存使用率和空闲率
[root@test1 ~]# free -m|awk 'NR==3{print $3/($3+$4)*100"%",$NF/($3+$NF)*100"%"}'
20.4641% 79.5359%

centOS7
//centOS7计算内存使用率和空闲率
[root@7-test1 ~]# free -m|awk 'NR==2{print ($2-$NF)/$2*100"%",$NF/$2*100"%"}'
30% 70%

2.3awk的一个坑

⚠️⚠️⚠️awk会把数字当成字符处理

//查看磁盘使用率
[root@test1 ~]# 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的列,结果不正确
[root@test1 ~]# 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会把数字当成字符处理,并没有把数字从大到小排序
[root@test1 ~]# seq 15|sort
1
10
11
12
13
14
15
2
3
4
5
6
7
8
9



解决awk把数字当成字符处理问题方法一
用指定分隔符的方式把数字和%分割开
//正确输出
[root@test1 ~]# df -h|awk -F'[% ]+'  '$5<9{print $1,$5,$NF}'
tmpfs 0 /dev/shm

//不正确输出
[root@test1 ~]# df -h|awk '$5<9{print $1,$5,$NF}'
/dev/sda3 14% /
tmpfs 0% /dev/shm
/dev/sda1 19% /boot


解决awk把数字当成字符处理问题方法二
让awk知道进行数字比较,某一列加0
//正确输出
[root@test1 ~]# df -h|awk 'NR>1 && $5+0<9{print $1,$5,$NF}'
tmpfs 0% /dev/shm

//不正确输出
[root@test1 ~]# df -h|awk 'NR>1 && $5<9{print $1,$5,$NF}'
/dev/sda3 14% /
tmpfs 0% /dev/shm
/dev/sda1 19% /boot

三、运算表达式

示例1:打印/etc/passwd第三列与10相乘大于5000的内容

[root@test1 ~]# 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的内容,并打印第一列和第三列

[root@test1 ~]# 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内容如下
[root@test1 ~]# cat test.txt 
a 1 2 3 4 5
b 1 2 3 4 5
a 5 6 7 8 9

[root@test1 ~]# awk '/a/{print $2+10}' test.txt 
11
15
[root@test1 ~]# awk '/a/{print $2-10}' test.txt 
-9
-5
[root@test1 ~]# awk '/a/{print $2*10}' test.txt 
10
50
[root@test1 ~]# awk '/a/{print $2/10}' test.txt 
0.1
0.5
[root@test1 ~]# awk '/a/{print $2%10}' test.txt 
1
5
[root@test1 ~]# awk '/a/{print $2**10}' test.txt 
1
9765625

四、逻辑操作符和复合模式

4.1逻辑操作符

符号 含义
&& 逻辑与
**\ \ ** 逻辑或
逻辑非

示例1:打印/etc/passwd文件中用户名为root并且打印uid小于15的行

//文件中第三列是UID
[root@test1 ~]# awk -F: '$1~/root/ && $3<=1' /etc/passwd 
root:x:0:0:root:/root:/bin/bash

示例2:打印用户名为root或第三列大于500的行

[root@test1 ~]# 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 ]

示例:

//文件t.txt内容如下
[root@test1 ~]# cat t.txt 
student1 98
student2 99
student3 93
student4 78
student5 85

根据学生成绩判断学生成绩是否为优秀,这里规定分数大于90是优秀,低于90非优秀
//非三元运算写法
[root@test1 ~]# awk '{if($2>90){print $1,"优秀"}else{print $1,"不优秀"}}' t.txt 
student1 优秀
student2 优秀
student3 优秀
student4 不优秀
student5 不优秀


//三元运算写法一        结果 = 条件 ? 结果1:结果2
[root@test1 ~]# 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


#可以使用三元运算符统计个数
//三元运算写法二        条件 ? 表达式1 : 表达式2
[root@test1 ~]# awk '{$2>90?a++:b++}END{print a,b}' t.txt 
3 2
a表示符合条件的,b表示不符合条件的,大于90分的有3个,低于90分的有2

至今没懂的一道题🦙🦙🦙

文件内容
[root@test1 ~]# cat lessons.txt 
634751 预排
568688 预排
386760 删除
619373 预排
428491 预排
487563 完成
603342 完成
436339 完成
结果:
删除  386760
完成  487563,603342,436339
预排  634751,568688,619373,428491

[root@test1 ~]# 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

[root@test1 ~]# 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

方法一
[root@test1 ~]# 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

方法二
[root@test1 ~]# 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
泡泡吐肥皂o © gitbook.pptfz.top 2021 all right reserved,powered by Gitbook文件修订时间: 秃笔南波湾!!!

results matching ""

    No results matching ""