欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

04.21 三剑客之老大awk命令详解

程序员文章站 2022-06-01 16:52:45
...

第一章 awk执行过程

1. awk版本信息

[root@Never-downtime ~]# awk --version
GNU Awk 3.1.7

2. awk参数模式动作
模式既pattem,可以类似理解成sed的模式匹配,可以由表达式组成,也可以是两个正斜杠之间的正则表达式。
比如NR==1,这就是模式,可以把他理解为一个条件。
动作即action,是由在大括号里面的一条或多条语句组成,语句之间使用分号隔开。如下awk使用格式。
04.21 三剑客之老大awk命令详解

3. awk执行过程

1读取一行>>
2根据模式/条件判定是否是要处理的行(NR>=2)>>
3如果不是则读取下一行,直到文件的结尾>>
4如果是对读取的行进行动作(action)处理>>
5处理完了继续读取文件的下一行 重复操作直至文件末尾。

第二章 awk记录和字段

1. 行和列
接下来我们给大家带来两个新概念记录和字段,这里为了方便大家理解可以把记录就当做行即记录==行,字段相当于列,字段==列。

名称 含义
record 记录、行
field 域、区域、字段、列

awk默认情况下每一行都是一个记录(record)
RS即record separator输入数据记录分隔符,每一行是怎么没的,表示每个记录输入的时候的分隔符,即行与行之间如何分割。
NR即number of record记录(行)号,表示当前正在处理的记录(行)的号码。
ORS即output record separator输出记录分隔符。
awk使用内置变量RS来存放输入记录分隔符,RS表示的输入的记录分隔符,这个值可以通过BEGIN模块重新定义修改。

[root@Never-downtime files]# cat awkfile.txt 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin

awk 'BEGIN{RS="/"}{print NR,$0}' awkfile.txt

2. awk记录知识小结
NR(number of record)存放着每个记录的号(行号)读取新行时候会自动+1
RS(record separator)是输入数据的记录/行标志,简单理解就是可以指定每个记录的结尾标志。RS作用就是表示一个记录的结束。
当我们修改了RS的值,最好配合NR行来查看变化,也就是修改了RS的值通过NR查看结果,调试awk程序。
ORS输出数据的记录的分隔符。可以通过修改RS的值,然后配合NR(行)来查看变化,也就是修改了RS的值通过NR查看结果,调试awk程序。

3. 字段(列)
每条记录都是由多个区域(field)组成的,默认情况区域之间的分隔符是由空格(即空格或制表符)来分隔,并且将分隔符记录在内置变量FS中,每行记录的区域数保存在awk的内置变量NF中。
04.21 三剑客之老大awk命令详解

4. FS与OFS
(1)FS即field separator,输入字段(列)分隔符。分隔符就是菜刀,把一定字符串切位很多个区域。
(2)awk -F 实际上修改的就是FS的内容,相当于 awk ‘BEGIN{FS=”:”}’
(3)NF即number of fileds,表示一行中列(字段)的个数,可以理解为菜刀切过一行后,切成了多少份。
(4)OFS输出字段(列)分隔符。
(5)awk使用内置变量FS来记录区域分隔符的内容,FS可以在命令行上通过-F参数来更改,也可以通过BEGIN模块来更改。
(6)然后通过nn1取第一个区域,2NF取最后一个区域。
04.21 三剑客之老大awk命令详解

5. 记录与字段(行与列)小结

小结
RS记录分隔符,表示每行的结束标志。
NR行号(记录号)
FS字段分隔符,每列的分隔标志或结束标志。
NF就是每行有多少列,每个记录中字段的数量。
$符号表示取某个列(字段),$1,$2,$NF
NF(number of field)表示记录中的区域(列)数量,$NF取最后一个列(区域)
FS 字段(列)分隔符, awk -F “:” ===== awk ‘BEGIN{FS=”:”}’
NR number of record 行号
分隔符就是结束标识
记录与区域,就是所谓的行与列 即(RS,FS)

第三章 awk正则匹配操作符

awk 正则匹配操作符 含义
~ 用于对记录或区域的表达式进行匹配
!~ 用于表达与~相反的意思

1. 案例
处理文件test.txt内容,将域名取出并根据域名进行计数排序处理

http://www.etiantian.org/index.html
http://www.etiantian.org/1.html
http://post.etiantian.org/index.html
http://mp3.etiantian.org/index.html
http://www.etiantian.org/3.html
http://post.etiantian.org/2.html

[aaa@qq.com files]# awk -F/ '{print $3}' test.txt |egrep -o [a-zA-Z0-9]|sort|uniq -c
      1 3
     12 a
      6 e
      6 g
     12 i
      1 m
     12 n
      8 o
      3 p
      6 r
      2 s
     14 t
      9 w

2. 环境搭建

mkdir -p /server/files/
cat >>/server/files/reg.txt<<EOF
Zhang Dandan    41117397   :250:100:175
Zhang Xiaoyu    390320151  :155:90:201
Meng  Feixue    80042789   :250:60:50
Wu    Waiwai    70271111   :250:80:75
Liu   Bingbing  41117483   :250:100:175
Wang  Xiaoai    3515064655 :50:95:135
Zi    Gege      1986787350 :250:168:200
Li    Youjiu    918391635  :175:75:300
Lao   Nanhai    918391635  :250:100:175
EOF

3. 显示姓Zhang的人的第二次捐款金额及她的名字

[aaa@qq.com8 files]# awk -F "[ :]+" 'NR<=2{print $2,$(NF-1)}' reg.txt 
Dandan 100
Xiaoyu 90

[aaa@qq.com8 files]# awk -F "[ :]+" '/^Zhang/{print $2,$(NF-1)}' reg.txt 
Dandan 100
Xiaoyu 90

4. 显示Xiaoyu的姓氏和ID号码

[root@Never-downtime files]# awk 'NR==2{print $1,$3}' reg.txt 
Zhang 390320151

[root@web02-8 files]# awk '/Xiaoyu/{print $1,$3}' reg.txt 
Zhang 390320151

5. 显示所有以41开头的ID号码的人的全名和ID号码

[aaa@qq.com8 files]# awk '$3~/^41/{print $1,$2,$3}' reg.txt 
Zhang Dandan 41117397
Liu Bingbing 41117483

6. 显示所有以一个D或X开头的人名全名

[aaa@qq.com8 files]# awk '$2~/^[DX]/{print $1,$2}' reg.txt 
Zhang Dandan
Zhang Xiaoyu
Wang Xiaoai

7. 显示所有ID号码最后一位数字是1或5的人的全名

[aaa@qq.com8 files]# awk '$3~/[15]$/{print $1,$2}' reg.txt 
Zhang Xiaoyu
Wu Waiwai
Wang Xiaoai
Li Youjiu
Lao Nanhai

[aaa@qq.com8 files]# awk '$(NF-1)~/1$|5$/{print $1,$2}' reg.txt 
Zhang Xiaoyu
Wu Waiwai
Wang Xiaoai
Li Youjiu
Lao Nanhai

8. 显示Xiaoyu的捐款.每个值时都有以$开头.如$520$200$135

[root@web02-8 files]# awk 'BEGIN{FS=":" ;OFS="$"}NR==2{print "$"$2,$3,$NF}' reg.txt 
$155$90$201

[root@web02-8 files]# awk -F ":" '/Xiaoyu/{print "$"$2"$"$3"$"$4}' reg.txt 
$155$90$201

[root@web02-8 files]# awk  'NR==2{gsub(/:/,"$");print $NF}' reg.txt 
$155$90$201

9. 显示所有人的全名,以姓,名的格式显示,如Meng,Feixue

[root@Never-downtime files]# awk 'BEGIN{OFS=","}{print $1,$2}' reg.txt 
Zhang,Dandan
Zhang,Xiaoyu
Meng,Feixue
Wu,Waiwai
Liu,Bingbing
Wang,Xiaoai
Zi,Gege
Li,Youjiu
Lao,Nanhai

[root@Never-downtime files]# awk '{print $1","$2}' reg.txt 
Zhang,Dandan
Zhang,Xiaoyu
Meng,Feixue
Wu,Waiwai
Liu,Bingbing
Wang,Xiaoai
Zi,Gege
Li,Youjiu
Lao,Nanhai

第四章 BEGIN模式

BEGIN{}模块在awk读取文件之前就执行,一般用来定义我们的内置变量(预定义变量,eg,FS,RS),可以输出表头
BEGIN模式之前我们有在示例中提到,自定义变量,给内容变量复制等,都使用过。需要注意的是BEGIN模式后面要接一个action动作操作,包含在大括号内。awk必须在对输入文件进行任何处理前先执行BEGIN里的动作(action)。
我们可以不要任何输入文件,就可以对BEGIN模块进行测试,因为awk需要先执行完BEGIN模式,才对输入文件做处理。BEGIN模式常常被用来修改内置变量ORS、RS、FS、OFS等的值。

1. 读取文件前执行

[aaa@qq.comNever-downtime files]# awk -F ":"  'BEGIN{print "NAME","UID"}{print $1,$3}'   awkfile.txt  |column -t
NAME      UID
root      0
bin       1
daemon    2
adm       3
lp        4
sync      5
shutdown  6
halt      7
mail      8
uucp      10

2.作用1:定义变量内容
例如RS、ORS、FS/—F 、OFS

[aaa@qq.com files]# awk 'BEGIN{name="hello";print name}'
hello

3. 作用2:计算器

[root@Never-downtime files]# awk 'BEGIN{print 10/3}'
3.33333

4. 取eth0的ip

[aaa@qq.com files]# ifconfig eth0 |awk -F "(addr:)|(Bcast:)" 'NR==2{print $2}'
192.168.56.129

[aaa@qq.com files]# ifconfig eth0 |awk -F "[ :]+" 'NR==2{print $4}'
192.168.56.129

[aaa@qq.com files]# ifconfig eth0 |awk -F "[^0-9.]+" 'NR==2{print $2}'
192.168.56.129

[aaa@qq.com files]# ifconfig eth0|awk 'BEGIN{FS="(addr:)|(Bcast:)"}NR==2{print $2}'
192.168.56.129

[aaa@qq.com files]# ifconfig eth0|awk 'BEGIN{FS="[ :]+"}NR==2{print $4}'
192.168.56.129

[aaa@qq.com files]# ifconfig eth0|awk 'BEGIN{FS="[^0-9.]+"}NR==2{print $2}'
192.168.56.129

第五章 END模式

END在awk读取完所有的文件的时候,再执行END模块,一般用来输出一个结果(累加,属组结果),也可以是和BEGIN模块类似的结尾表示信息。

1.统计文件有多少行

[root@web02-8 files]# awk '{i=i+1;print i}' reg.txt 
1
2
3
4
5
6
7
8
9

[root@web02-8 files]# awk '{i=i+1}END{print i}' reg.txt 
9

[root@Never-downtime files]# cat -n reg.txt |tail -1
9   uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

[root@Never-downtime files]# sed -n 'p' reg.txt |wc -l 
9

第六章 awk执行过程

(1)命令行的赋值(-F或-v)
(2)执行BEGIN模式里面的内容
(3)开始读取文件
(4)判断条件(模式)是否成立
(5)成立则执行对应动作里面的内容
(6)读取下一行,循环判断
(7)直到读取到最后一个文件的结尾
(8)最后执行END模式里面的内容

[root@Never-downtime files]# a=1 
[root@Never-downtime files]# b=2
[root@Never-downtime files]# awk 'BEGIN{print a+b}'
0
[root@Never-downtime files]# awk -v a=1 -v b=2 'BEGIN{print a+b}'
3
[root@Never-downtime files]# awk -v a=$(hostname) 'BEGIN{print a}'
Never-downtime

第七章 awk属组

变量相当于一室的房子,每次只能住一家人,如果想往里面放很多种不同的内容,或者住不同的家庭,就需要用到多个变量,可以这不是很方便。所以公寓诞生了,即awk数组。
04.21 三剑客之老大awk命令详解

[aaa@qq.com files]# awk 'BEGIN{hotel[110]="xioyu";hotel[119]="bingbing";hotel[401]="tandao";for (pol in hotel) print pol,hotel[pol]}'
110 xioyu
401 tandao
119 bingbing

[aaa@qq.com8 files]# awk 'BEGIN{h[110]="xiaoyu";h[119]="bingbing";h[401]="tandao";for (a in h)print a,h[a]}'
119 bingbing
110 xiaoyu
401 tandao

04.21 三剑客之老大awk命令详解

awk属组总结
(1)awk数组是分析日志最常用的功能,也是玩转awk必会的部分。
(2)awk数组的名字就像九点的名字一样,学习的时候我们可以用hotel,h等等,后面再使用的时候要命名规范一些,要不再次使用的时候就不理解了。
(3)awk数组的元素名字就像房间号码,房间号码用的一般就是你想要处理的东西,比如统计ip地址,比如统计url。可以把ip,url作为房间号码。
(4)遇到awk数组的元素的内容就像房间里面住的人,一般就是放我们想要的结果,或者计算的结果,即把计算结果放在房间中,
(5)遇到awk数组的处理一般都是进行统计,这时候我们会把最后的结果在END模块里面输出。
(6)输出awk数组的结果,就是现实房间里面的内容,即查房。
(7)awk的查房是通过for (pol in hotel)这种形式来完成的,fot表示循环,pol表示警察是一个变量名字,in表示去查房,hotel表示酒店名称,合起来就是警察去酒店查房, 查完一个继续查下一个。
(8)在查房过程中pol警察知道房间号码,也就是说pol变量中的内容就是房间号码。
(9)要看房间中的内容,首先要知道酒店名称,然后就是房间号码即hotel[pol]。
(10)要熟练使用awk数组在开始的时候就要学会一步一步看awk如何执行的即可。

碰到问题先拆解:大象放冰箱一步一步来
第一个里程碑##取出想要的内容
第二个里程碑##创建数组
第三个里程碑##进行统计

扩展案例
假如现在有个文本,格式如下:
a 1
b 3
c 2
d 7
b 5
a 3
g 2
f 6
d 9
即左边是随机字母,右边是随机数字,要求写个脚本使其输出格式为:
a 4
b 8
c 2
d 16
f 6
g 2
即将相同的字母后面的数字加在一起,按字母的顺序输出。

[aaa@qq.com8 files]# awk '{AA[$1]=AA[$1]+$2}END{for (a in AA)print a,AA[a]}' test.txt 
a 4
b 8
c 2
d 16
f 6
g 2