基础知识梳理之awk命令
awk简介
一种怪异的语言
模式扫描和处理
awk不仅仅是linux中的一个命令,而且是一种编程语言,可以用来处理数据和生成报告。处理的数据可用是一个或多个,可以是来自标准输入,也可以通过管道获取标准输入,awk可以在命令行上直接编辑命令进行操作,也可以编写awk程序进行更为复杂的运用。
awk环境简介
[root@oldboy34 ~]# cat /etc/redhat-release CentOS release 6.8 (Final) [root@oldboy34 ~]# uname -r 2.6.32-642.el6.x86_64 [root@oldboy34 ~]# awk --version GNU Awk 3.1.7
awk格式
awk指令是由,模式,动作,或模式和动作的组合组成
模式即pattern,可以类似理解成sed的模式匹配,可以由表达式组成,也可以由表达式组成,也可以是两个正斜杠之间的正则表达式
动作即action,是由在大括号里面的一条或多条语句组成,语句之间使用分号隔开。如awk使用格式:
awk [options] 'pattern{action}' # awk参数 模式动作
awk处理的内容可以来自标准输入(<)、一个或多个文本文件或管道

pattern即模式,也可以理解为条件
action即动作,可以理解为干啥
awk执行过程

案例文件的创建
mkdir /server/files/ -p
head /etc/passwd > /server/files/awkfile.txt
记录和字段
|
名称 |
含义 |
|
record |
记录,行 |
|
field |
域,区域,字段,列 |
awk对每个要处理的输入数据认为都是具有格式和结构的,而不仅仅是一堆字符串。默认情况下,每一行内容都是一条记录,并以换行符分割(\n)结束
awk记录分割符-RS
字段行

awk默认情况下每一行都是一个记录(record)
RS即record separator输入输入数据记录分割符,每一行是怎么没的,表示每个记录输入的时候的分割符,即行与行之间如何分割。
NR即number of record记录(行)号,表示当前正在处理的记录(行)的号码。
ORS即output record separator输出记录分隔符。
awk使用内置变量RS来存放输入记录分隔符,RS表示的是输入的记录分隔符这个值可以通过BEGIN模块重新定义修改。
示例:
[root@oldboy34 files]# head -2 awkfile.txt root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin [root@oldboy34 files]# awk 'BEGIN{RS="/"}{print NR,$0}' awkfile.txt 1 root:x:0:0:root: 2 root: 3 bin 4 bash bin:x:1:1:bin: 5 bin: 6 sbin 7 nologin
以:为没一行的结束
[root@oldboy34 files]# head -2 awkfile.txt root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin [root@oldboy34 files]# awk 'BEGIN{RS=":"}{print $1}' awkfile.txt root x 0 0 root /root /bin/bash
以连续的数字为每一行的结束
[root@oldboy34 files]# awk 'BEGIN{RS="[0-9]+"}{print NR,$0}' awkfile.txt 1 root:x: 2 : 3 :root:/root:/bin/bash
对$0的认识
awk使用$0来表示整条记录。记录分隔符存在RS变量中,或者说每一个记录以RS内置变量结束
awk对每行的记录号都有一个内置NR来保存,没处理完一条记录NR的值就会自动+1
说明
NR number of record,当前记录的记录号
$0 表示整行或者说整个记录
企业面试题:按单词出现频率降序排序(计算文件中每个单词的重复数)
注:(此处使用sort与uniq即可)
实验环境
[root@oldboy34 files]# sed -rn '1,10s#[^a-zA-Z]+# #gp' /etc/passwd >/server/files/count.txt [root@oldboy34 files]# cat count.txt root x root root bin bash bin x bin bin sbin nologin daemon x daemon sbin sbin nologin adm x adm var adm sbin nologin lp x lp var spool lpd sbin nologin sync x sync sbin bin sync shutdown x shutdown sbin sbin shutdown halt x halt sbin sbin halt mail x mail var spool mail sbin nologin uucp x uucp var spool uucp sbin nologin
解答
[root@oldboy34 files]# awk 'BEGIN{RS=" "}{print $0}' count.txt |sort |uniq -c 1 3 adm 1 bash 5 bin 2 daemon 3 halt 2 lp 1 lpd 3 mail 6 nologin 3 root 12 sbin 3 shutdown 3 spool 3 sync 3 uucp 4 var 10 x
awk记录知识小结
NR(number of record)存放着每个记录的号(行号)读取新行时候会自动+1
RS(record separator)是输入数据的记录分隔符,简单理解就是指定每个记录的结尾标志
RS作用就是表示一个记录的结束
当我们修改了RS的值,最好配合NR(行)来查看变化,也就是修改了RS的值通过NR查看结果,调试awk
ORS输出数据的记录的分隔符
字段列
每条记录都是由多个区域(field)组成,默认情况下区域之间的分隔符是由空格(即空格或制表符)来分隔,并且将分隔符记录在内置变量FS中。每行记录的区域数据保存在awk的内置变量NF中。
field有很多钟解释,域、记录、区域。

FS即field separator,输入字段(列)分隔符,分隔符就是菜刀,把一行字符串切为很多个区域
NF即number of fileds,表示一行中列(字段)的个数,可以理解为菜刀切过一行后,切成了多少份。
OFS输出字段(列)分割符
awk使用内置变量FS来记录区域分隔符的内容,FS可以在命令行上通过-F参数来更改,也可以通过BEGIN模块来更改
然后通过$n,n是整数,来取被切割后的区域,$1取第一个区域,$2取第二个区域,$NF取最后一个区域。
ORS与OFS简介
RS是输入记录分隔符
ORS表示输出记录分隔符(output record separator),决定awk如何输出一行(记录)的,默认是回车换行(\n)。
FS是输入区域分隔符,决定awk读入一行后如何再分为多少区域
OFS表示输出区域分隔符,决定awk输出每个区域的时候使用什么分隔他们

[root@oldboy34 files]# cat 123.txt aaa#bbb#ccc aaa#bbb#ccc aaa#bbb#ccc aaa#bbb#ccc aaa#bbb#ccc aaa#bbb#ccc aaa#bbb#ccc aaa#bbb#ccc aaa#bbb#ccc aaa#bbb#ccc aaa#bbb#ccc [root@oldboy34 files]# awk 'BEGIN{FS="#";OFS="|"}{print $1,$2,$3}' 123.txt aaa|bbb|ccc aaa|bbb|ccc aaa|bbb|ccc aaa|bbb|ccc aaa|bbb|ccc aaa|bbb|ccc aaa|bbb|ccc aaa|bbb|ccc aaa|bbb|ccc aaa|bbb|ccc aaa|bbb|ccc
字段记录小结
RS记录分隔符,表示每行的结束标志
NR行号(记录号)
FS字段分隔符,每列的分隔标志或结束标志
NF就是每行有多少列,每个记录中字段的数量
$符号表示取某个列(字段)
awk进阶
awk模式与动作
awk [options] 'pattern{action}' file # awk参数 模式动作
awk的模式都有几种
正则表达式为模式
比较表达式为模式
范围模式
特殊模式BEGIN和END
awk正则表达式练习题
实验环境
[root@oldboy34 files]# cat reg.txt 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
显示姓Zhang的人的第二次捐款金额及他的名字
[root@oldboy34 files]# awk -F "[ :]+" '$1~/^Zhang/{print $2,$5}' reg.txt Dandan 100 Xiaoyu 90
显示Xiaoyu的名字和ID号码
[root@oldboy34 files]# awk '$2~/^Xiaoyu$/{print $2,$3}' reg.txt Xiaoyu 390320151
显示所有以41开头的ID号码的人的全民和ID号码
[root@oldboy34 files]# awk '$3~/^41/{print $1,$2,$3}' reg.txt Zhang Dandan 41117397 Liu Bingbing 41117483
显示所有一个D或X开头人的全名
[root@oldboy34 files]# awk '$2~/^[DX]/' reg.txt Zhang Dandan 41117397 :250:100:175 Zhang Xiaoyu 390320151 :155:90:201 Wang Xiaoai 3515064655 :50:95:135
[root@oldboy34 files]# awk '$2~/^(D|X)/' reg.txt Zhang Dandan 41117397 :250:100:175 Zhang Xiaoyu 390320151 :155:90:201 Wang Xiaoai 3515064655 :50:95:135
显示所有ID号码最后一位数字是1或5的人的全名
[root@oldboy34 files]# awk '$3~/[15]$/' reg.txt Zhang Xiaoyu 390320151 :155:90:201 Wu Waiwai 70271111 :250:80:75 Wang Xiaoai 3515064655 :50:95:135 Li Youjiu 918391635 :175:75:300 Lao Nanhai 918391635 :250:100:175
显示Xiaoyu的捐款,每个值时都有以$开头,如$520$200$135
[root@oldboy34 files]# awk '$2~/Xiaoyu/{gsub(/:/,"$",$NF);print $NF}' reg.txt $155$90$201
显示所有人的全名,即姓,名的格式显示,如Meng,Feixue
[root@oldboy34 files]# awk '{print $2,$1}' reg.txt Dandan Zhang Xiaoyu Zhang Feixue Meng Waiwai Wu Bingbing Liu Xiaoai Wang Gege Zi Youjiu Li Nanhai Lao
比较表达式作为模式
|
运算符 |
含义 |
示例 |
|
< |
小于 |
x>y |
|
<= |
小于或等于 |
x<=y |
|
== |
等于 |
x==y |
|
!= |
不等于 |
x!=y |
|
> |
大于或等于 |
x>=y |
|
> |
大于 |
x<y |
|
以上的运算符是针对数字,下面两个运算符之前已有示例,针对字符串 |
||
|
~ |
与正则表达式匹配 |
x~/y/ |
|
!~ |
与正则表达式不匹配 |
x!~y |
案例
[root@oldboy34 files]# awk -F "[ :]" '$5>100' reg.txt Wu Waiwai 70271111 :250:80:75 Zi Gege 1986787350 :250:168:200 Li Youjiu 918391635 :175:75:300
找出/etc/passwd中第五列是root的行
[root@oldboy34 files]# awk -F: '$5=="root"' /etc/passwd root:x:0:0:root:/root:/bin/bash
范围模式
|
pattern1 |
, |
pattern2 |
|
从哪里来 |
到 |
哪里去 |
|
条件1 |
, |
条件2 |
案例1:
[root@oldboy34 files]# awk '/^root/,/^shut/' 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 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 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
awk 特殊模式-BEGIN模式与END模式
BEGIN模块
BEGIN模块在awk读取文件之前就执行,一般用来定义我们的内置变量(预定义变量,eg:FS,RS),可以输出表头
BEGIN模式之前我们有在示例中提到,自定义变量,给内容变量赋值等,都用过。需要注意的是BEGIN模式后面要紧跟一个action操作块,包含在大括号内。awk必须在对输入文件进行任何处理前先执行BEGIN里面的动作(action)。我们可以不要任何输入文件,就可以对BEGIN模块进行测试,因为awk需要先执行完BEGIN模式,才对文件做处理。BEGIN模式常常被用来修改内置变量ORS,RS,FS,OFS等值。
[root@oldboy34 files]# awk -F: 'BEGIN{print "username","UID"}{print $1,$3}' /server/files/awkfile.txt username UID root 0 bin 1 daemon 2 adm 3 lp 4 sync 5 shutdown 6 halt 7 mail 8 uucp 10
[root@oldboy34 files]# awk 'BEGIN{print 10/3}' 3.33333 [root@oldboy34 files]# awk 'BEGIN{print 10/3+1}' 4.33333 [root@oldboy34 files]# awk 'BEGIN{print 10/3+1/4*9}' 5.58333
awk中的概念简介
直接定义,直接使用即可
awk中的字母会被认为是变量,如果真的要给一个变量赋值字母(字符串),请用双引号。
[root@oldboy34 files]# awk 'BEGIN{a="yanghao";print a}' yanghao [root@oldboy34 files]# awk 'BEGIN{a=1;print a}' 1 [root@oldboy34 files]# awk 'BEGIN{a=123456;print a}' 123456
说明
没有文件awk依旧可以处理BEGIN模式下的动作(命令)
END模式
END在awk读取完所有的文件的时候,再执行END模块,一般用来输出一个结果(累加,数组结果),也可以是和BEGIN模块类似的结尾标识信息
[root@oldboy34 files]# awk 'BEGIN{print "hello world"}{print NR,$0}END{print "end of file"}' count.txt hello world 1 root x root root bin bash 2 bin x bin bin sbin nologin 3 daemon x daemon sbin sbin nologin 4 adm x adm var adm sbin nologin 5 lp x lp var spool lpd sbin nologin 6 sync x sync sbin bin sync 7 shutdown x shutdown sbin sbin shutdown 8 halt x halt sbin sbin halt 9 mail x mail var spool mail sbin nologin 10 uucp x uucp var spool uucp sbin nologin end of file
与BEGIN模式相对应的END模式,格式一样,但是END模式仅在awk处理完所有输入行后才处理.
企业案例3:统计/etc/services文件里面的空行数量
[root@oldboy34 files]# grep -c "^$" /etc/services 16 [root@oldboy34 files]# awk '/^$/{i=i+1}END{print i}' /etc/services 16
awk编程思想
1、先处理,最后在END模式输出
2、{print NR,$0}body模块处理,处理完毕后
3、END{print "end of file"}输出一个结果
几种常用的运算表达式
i=i+1 ====>i++ i=i+2 ====>i+=2 i=i+$0 ====>i+=$0
awk数组
|
指定分隔符 |
单引号 |
创建awk数组 |
取结果 |
单引号 |
|
|
awk -F "/+" |
, |
{hotel[$2]++} #类似i++ |
END{for (pol in hotel) print pol,hotel[pol]} |
, |
ur1.txt |
|
先处理后输出(END模块输出) |
|||||
[root@oldboy34 files]# awk 'BEGIN{hotel[110]="xiaoyu";hotel[119]="tandao";hotel[121]="feixue";print hotel[110],hotel[119],hotel[121]}' xiaoyu tandao feixue
统计每个域名出现的次数,对域名进行去重,并显示重复数量
测试环境
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@oldboy34 files]# awk -F "[/.]+" '{hotel[$2]++}END{for(pol in hotel) print pol,hotel[pol]}' ur1.txt www 3 mp3 1 post 2

浙公网安备 33010602011771号