您的位置:首页 > 其它

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

2017-07-12 11:49 141 查看

第一章 awk执行过程

1. awk版本信息

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


2. awk参数模式动作

模式既pattem,可以类似理解成sed的模式匹配,可以由表达式组成,也可以是两个正斜杠之间的正则表达式。

比如NR==1,这就是模式,可以把他理解为一个条件。

动作即action,是由在大括号里面的一条或多条语句组成,语句之间使用分号隔开。如下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中。



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)然后通过nn是整数,来取被切割后的区域,1取第一个区域,2取第二个区域,NF取最后一个区域。



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 
[root@Never-downtime 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的人的第二次捐款金额及她的名字

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

[root@web02-8 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号码

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


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

[root@web02-8 files]# awk '$2~/^[DX]/{print $1,$2}' reg.txt
Zhang Dandan
Zhang Xiaoyu
Wang Xiaoai


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

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

[root@web02-8 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. 读取文件前执行

[root@Never-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

[root@Never-downtime files]# awk 'BEGIN{name="hello";print name}'
hello


3. 作用2:计算器

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


4. 取eth0的ip

[root@Never-downtime files]# ifconfig eth0 |awk -F "(addr:)|(Bcast:)" 'NR==2{print $2}'
192.168.56.129

[root@Never-downtime files]# ifconfig eth0 |awk -F "[ :]+" 'NR==2{print $4}'
192.168.56.129

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

[root@Never-downtime files]# ifconfig eth0|awk 'BEGIN{FS="(addr:)|(Bcast:)"}NR==2{print $2}'
192.168.56.129

[root@Never-downtime files]# ifconfig eth0|awk 'BEGIN{FS="[ :]+"}NR==2{print $4}'
192.168.56.129

[root@Never-downtime 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数组。



[root@Never-downtime 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

[root@web02-8 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




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

即将相同的字母后面的数字加在一起,按字母的顺序输出。

[root@web02-8 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息