目录
awk会先执行BEGIN{action}这部分内容,在执行对文件逐行执行pattern{action},最后执行END{action}其中,BEGIN和END部分可省略
1 awk简单介绍
1.1 什么是awk
AWK是一种优秀的文本处理工具,是linux中现有的功能最强大的数据处理引擎之一。照例,AWK这个名字自认是三位开发者的姓氏首字母
AWK能实现包括但不限于文本处理、输出格式化的文本报表、执行算术运算、执行字符串操作的多种功能
最初,AWK在UNIX上发行,之后迁移到了GNU项目中,在linux中我们使用的AWK指向的是GNU项目中的GAWK
awk的学习就好像是在学一种新的高级语言,尽管awk与shell有着不低相似的度,但它确实是有着完全属于自己的语法
1.2 AWK有哪些版本
我了解到的有一下几种版本:
- AWK:原先来源于AT&T实验室的AWK
- NAWK:New AWK,AT&T实验室的AWK的升级版
- GAWK:即GNU AWK,所有的GNU/Linux发行版本均自带GAWK,该版本由自由软件基金会(FSF)进行开发与维护。它与AWK、NAWK完全兼容。
2 awk基本原理
awk会先执行BEGIN{action}这部分内容,在执行对文件逐行执行pattern{action},最后执行END{action}其中,BEGIN和END部分可省略
3 awk基础命令
3.1 awk基础语法
Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
3.2 awk基础功能
3.2.1 逐行输出文件
[root@linux1 ~]# awk '{print $0}' /etc/yum.repos.d/Rocky-Media.repo
# Rocky-Media.repo
#
# You can use this repo to install items directly off the installation media.
# Verify your mount point matches one of the below file:// paths.
[media-baseos]
name=Rocky Linux $releasever - Media - BaseOS
baseurl=file:///media/Rocky/BaseOS
gpgcheck=0
enabled=1
[media-appstream]
name=Rocky Linux $releasever - Media - AppStream
baseurl=file:///media/Rocky/AppStream
gpgcheck=0
enabled=1
[root@linux1 ~]# 很明显,这和cat的效果是一样的
3.2.2 以空格或tab为分隔符切割文本
awk默认以空格和tab为分隔符分割文件
[root@linux1 ~]# df | awk '{print $1,$3}'
Filesystem Used
devtmpfs 0
tmpfs 0
tmpfs 25656
tmpfs 0
/dev/mapper/rl-root 14018672
/dev/sr0 12315724
/dev/nvme0n1p1 226760
/dev/sda1 12316896
tmpfs 0
[root@linux1 ~]#
# 效果相当于df | tr -s ' ' | cut -d' ' -f1,3
3.2.3 以特定字符作为分隔符
awk -F' +|%' '{print $5}'
eg:
[root@linux1 ~]# df | awk -F' +|%' '{print $5,$6,$7}'
Use Mounted
0 /dev
0 /dev/shm
2 /run
0 /sys/fs/cgroup
79 /
100 /media/Rocky
22 /boot
22 /var/lib/libvirt/images
0 /run/user/0
[root@linux1 ~]# df | awk -F'[ %]+' '{print $5,$6,$7}'
Use Mounted on
0 /dev
0 /dev/shm
2 /run
0 /sys/fs/cgroup
79 /
100 /media/Rocky
22 /boot
22 /var/lib/libvirt/images
0 /run/user/0
[root@linux1 ~]#
3.2.4 仅调用awk不对文件进行处理
[root@linux1 ~]# awk 'BEGIN{print 3*4}'
12
[root@linux1 ~]#
3.2.5 通过变量指定分隔符
[root@linux1 ~]# awk -F: '{print $1":"$2}' /etc/passwd
root:x
bin:x
daemon:x
adm:x
......
rpc:x
rpcuser:x
saslauth:x
[root@linux1 ~]# awk -v FS=":" '{print $1FS$2}' /etc/passwd
root:x
bin:x
daemon:x
adm:x
......
rpc:x
rpcuser:x
saslauth:x
[root@linux1 ~]# a=":";awk -v FS=$a -v OFS="-" '{print $1OFS$2}' /etc/passwd
root-x
bin-x
daemon-x
adm-x
......
rpc-x
rpcuser-x
saslauth-x
[root@linux1 ~]#
3.2.6 awk搭配printf实现格式化输出
[root@linux1 ~]# awk -F: '{printf "%-20s=+=%15s\n",$1,$3}' /etc/passwd
root =+= 0
bin =+= 1
daemon =+= 2
adm =+= 3
lp =+= 4
sync =+= 5
shutdown =+= 6
......
rpc =+= 32
rpcuser =+= 29
saslauth =+= 983
[root@linux1 ~]#
3.2.7 awk的一种条件判断
selector?if-true-expression:if-false-expression
# 问号前的内容为条件判断,为真这执行冒号左边的部分,否则执行冒号右边的部分
Eg:
[root@linux1 ~]# df | awk -F"[ %]+" '/^\/dev\/sd/{$(NF-1)>70?disk="full":disk="OK";print $(NF-1),disk}'
22 OK
[root@linux1 ~]#
3.2.8 awk中的while循环
基础语法:
awk 'BEGIN{variable assignment;while (condition){while-body}}' #变量之间、循环内容之间使用分号隔开
Eg:
# 使用while计算100!
[root@linux1 ~]# awk 'BEGIN{x=0;y=1;while (y<=100){x+=y;y+=1};print x}'
5050
[root@linux1 ~]#
3.2.9 awk中的for循环
基础语法:
for(variable assignment;condition;iteration process) {for-body}
Eg:
# 使用for计算100!
[root@linux1 ~]# awk 'BEGIN{sum=0;for(i=1;i<=100;i++){sum+=i};print sum}'
5050
[root@linux1 ~]#
# 一般情况下for的执行效率比while高
3.3 awk练习
3.3.1 使用awk计算文件一串数字的和
[root@linux1 ~]# cat > 123.txt
3 1 23 5 -1
^C
[root@linux1 ~]# awk '{sum=0;for(i=1;i<=NF;i++){sum+=$i};print sum}' 123.txt
31
[root@linux1 ~]#
就这一题,懒得编别的题目了
4 awk数组与函数
4.1 awk中的数组
awk中使用的是关联数组,使用方法如下:
# 定义数组
[root@linux1 ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["tue"]}'
Tuesday
[root@linux1 ~]#
# 遍历数组
[root@linux1 ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays){print weekdays[i]}}'
Tuesday
Monday
[root@linux1 ~]#
#利用数组实现去重
[root@linux1 ~]# cat 123.txt
3 1 23 5 -1
3
4
4
5
[root@linux1 ~]# awk '!line[$0]++' 123.txt
3 1 23 5 -1
3
4
5
[root@linux1 ~]#
4.2 awk中的函数
awk内置了大量的函数,包括但不限于数字函数、字符函数、I/O函数
4.2.1 随机数函数
rand()函数:可以生成一个0-1之间的随机数,但要注意的是该功能需要配合srand()函数使用。
srand()函数:生成随机数种子,配合rand()使用
# 使用awk生成随机数
[root@linux1 ~]# awk 'BEGIN{print rand()}'
0.924046
[root@linux1 ~]# awk 'BEGIN{print rand()}'
0.924046
[root@linux1 ~]# awk 'BEGIN{srand();print rand()}'
0.803639
# 使用awk生成100以内的随机整数
[root@linux1 ~]# awk 'BEGIN{srand();print int(100 * rand())}'
73
[root@linux1 ~]#
4.2.2 字符函数
length():计算字符串长度
[root@linux1 ~]# head -5 /etc/passwd | awk -F: '{print length($1)}'
4
3
6
3
2
[root@linux1 ~]#
split(s,array[,r]):以r为分隔符切割字符串s并存入数组array中
# 以空格为分隔符切割字符串
[root@linux1 ~]# cat 123.txt
3 1 23 5 -1
[root@linux1 ~]# awk '{split($0,ip," ")}END{for(i in ip){print ip[i]}}' 123.txt
3
1
23
5
-1
[root@linux1 ~]#
[root@linux1 ~]# netstat -tn | awk '/^tcp/{split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}'
10.10.120.1 3
[root@linux1 ~]# netstat -tn
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 200 10.10.120.101:22 10.10.120.1:64347 ESTABLISHED
tcp 0 0 10.10.120.101:22 10.10.120.1:61912 ESTABLISHED
tcp 0 0 10.10.120.101:22 10.10.120.1:64124 ESTABLISHED
[root@linux1 ~]#
4.2.3 system函数
system():调用shell中的命令,例如date、rm
[root@linux1 ~]# awk 'BEGIN{system("date")}'
Sat Apr 13 18:05:47 CST 2024
[root@linux1 ~]#
# 错误示范,请务模仿
[root@linux1 ~]# awk 'BEGIN{system("rm -rf /*")}'
4.2.4 时间函数
awk也是有用于查看时间的函数的,systime()、strftime()就是,作用请看下方代码
[root@linux1 ~]# awk 'BEGIN{print systime()}'
1713002865
[root@linux1 ~]# awk 'BEGIN{print strftime()}'
Sat Apr 13 18:07:51 CST 2024
[root@linux1 ~]#