AWK从入门到精通

 

第1章 awk基础入门

要弄懂awk程序,必须熟悉了解这个工具的规则,

1.2 awk简介

1.2.1 一种名字怪异的语言

1.2.2 模式扫描和处理

awk不仅仅是Linux中的一个命令,而且是一种编程语言,可以用来处理数据和生成报告,处理的数据可以是一个或者多个文件,可以是来自标准输入,也可以是通过管道获取标准输入,awk可以在命令行上直接编辑命令进行操作,也可以编写成awk程序来进行运用,本章主要讲解awk命令行的运用,较为复杂的程序会包含在以后的课程中

  回顾sed命令,把文件当做流水一样处理

1.3 学过awk可以掌握的内容

 1记录和字段

 2 模式匹配:模式与动作

 3 基本的awk执行过程

 4awk常用的内置变量(预定义变量)

 5 awk数组(工作常用的)

 6awk语法:循环,条件

 7awk常用的函数

 8 向awk传递参数

 9awk引用shell变量

10 awk小程序及调试思路

1.4 awk命令

awk -v RS=":"  与‘BEGIN{RS=":"}’一样

uniq 合并相同行    -c  将相同行相加输出

sort  排序, 默认按照字母顺序排序   -r 逆向排序     -n  排序

culomn -t      使行,列对齐

awk的默认的FS 分隔符 空格序列  TAB键 一个或者多个空格 ,都认为是一个整体

OFS不支持正则表达式

FS=-F  指定分隔符

posix   使awk支持扩展正则表达式,如:'/0{2,3}/'

awk中  $N==root    要写成$N=="root"   如果不佳双引号,awk会把等于看成是一个变量

例子:

[root@oldboy32-vm1~]# awk -F ":"'NR<=5{print $1,$3}' /etc/passwd

root 0

bin 1#awk 参数 '条件(找谁){动作(干啥)}' /etc/passwd

1.5 模式及pattern,可以类似理解成sed的模式匹配,可以由表达式组成,也可以是俩个正斜杠之间的正则表达式,比如:NR==1,这就是模式,可以理解为一个条件。

1.6 动作即action,是由在大括号里面的一条或者多条语句组成,语句之间使用分号隔开,如下awk使用格式

awk处理的内容可以来自标准输入(>),一个或者多个文本或管道

模式动作里面分俩部分,大括号外面的叫找谁里面的叫干啥

1.7 awk执行过程

1 首先读取一行

2 模式是我要处理的行吗?

3 如果是,则对读入行执行动作里的命令

4 如果否,则重复上面的过程直到最后一个文件结尾

5 END模块

6 结束

1.8 接下来说俩个新概念:记录和字段,这里为了方便理解可以把记录当做行记录===行,字段相当于列,字段===列。

record

记录 ,行

field

域,区域,字段,列

1.9 awk记录分隔符 -RS

记录分隔符 -每一个记录是如何结束的

[root@zxw files]# cat reg.txt

Zhang (FS)Dandan41117397:250:100:175$0

RS

Zhang (FS)Xiaoyu390320151:155:90:201$0

RS

Meng(FS)Feixue80042789:250:60:50$0

RS

1.9.1 awk默认情况下每一行都是一个记录

1.9.2 RS即record separator输入数据记录分隔符,每一行是怎么来的,表示每个记录输入的时候的分隔符,即行与行之间如何分割。

例子:

awk指定RS分割符号:

[root@oldboy32-vm1files]# head -2 awkfile.txt

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

[root@oldboy32-vm1files]# awk 'BEGIN{RS="/"}{print NR,$0}' awkfile.txt

1root:x:0:0:root:

2 root:

3 bin

4 bash

1.9.3 NR即number of record 记录行号,表示当前正在处理的行的号码

取oldboy

[root@oldboy32-vm1files]# echo "I am oldboy,my qq is31333741">>/server/files/oldboy.txt

[root@oldboy32-vm1files]# cat oldboy.txt

I am oldboy,myqq is 31333741

[root@oldboy32-vm1files]# echo oldboy,31333741

oldboy,31333741

[root@oldboy32-vm1files]# awk -F " |," '{print $3,$NF}'oldboy.txt

oldboy31333741

[root@oldboy32-vm1files]# awk -F " |," '{print$3","$NF}' oldboy.txt

oldboy,31333741

[root@oldboy32-vm1files]# awk -F "[ ,]" '{print$3","$NF}' oldboy.txt

oldboy,31333741

1.9.4 ORS即output record separator 输出记录分隔符。

1.9.5 awk使用内置变量RS来存放输入记录分隔符,RS表示的是输入的记录分隔符,这个值可以通过BEGIN模块重新定义修改。

1.10 思路

1 让所有的单词排成一列,这样每个单词都是单独的一行

2 设置RS的值为空格

3 将文件里面的所有空格替换为回车换行符“\n”

4 grep所有连续的字母,grep -o 参数让他们排成一排

整体思路 :想办法让所有单词排成一行,站成一队,排序,合并重复的,显示重复数量

1.11 awk记录知识小结

1.11.1 NR存放着每个记录的号(行号),读取新行时候会自动加1(+1)

1.11.2 RS是输入数据的记录的分隔符,简单理解就是可以指定每个记录的结尾标致

1.11.3 RS作用就是表示一个记录的结束

1.11.4 当我们修改了RS的值,最好配合NR来查看变化,也就是修改了RS的值通过NR查看结果,调试awk程序。

1.11.5 ORS输出数据的记录的分隔符

ORS

[root@oldboy32-vm1files]# cat ors.txt

a

b

c

[root@oldboy32-vm1files]# awk 'BEGIN{ORS="oldboy"}{print $0}'ors.txt

aoldboyboldboycoldboy[root@oldboy32-vm1files]#

1.12 awk学习技巧一则

大象放冰箱分几步?  打开冰箱门,把大象放进去,关上冰箱门。awk也是一样,一步一步来,先修改RS,然后用NR调试,看看到底如何分割的,然后通过sort排序,uniq去掉重复的。

1.13 字段(字段)

每条记录都是由多个区域组成的,默认情况下区域之间的分隔符是由空格(即空格或者制表符)来分割,并且将分隔符记录在内置变量FS中每行记录的区域数据保存在awk的内置变量NF中

约定:

      field有很多多种解释,域,记录,区域,为了方便理解统一使用区域表示field。

Zhang (FS)Dandan41117397:250:100:175$0

RS

Zhang (FS)Xiaoyu390320151:155:90:201$0

RS

Meng (FS) Feixue80042789:250:60:50$0

RS

Wu(FS)Waiwai70271111:250:80:75$0

RS

Liu(FS)Bingbing41117483:250:100:175   $0

RS

Wang(FS)Xiaoai3515064655:50:95:135  $0

RS

Zi(FS)Gege1986787350:250:168:200   $0

1.14 FS

FS即field separator,输入字段(列)分隔符,分隔符就是菜刀,把一行字符串切为很多个区域。

NF即number offields ,表示一行中列的个数,可以理解为菜刀切过一行后,切成了多少份,OFS输出字段(列)分隔符

awk使用内置变量FS来记录区域分隔符的内容,FS可以在命令行上通过 F 参数来更改,也艺客通过BEGIN模块来更改。

然后通过$n ,n是整数,来取北切割后的区域,$1取第一个区域,$2取第二个区域,$NF取最后一个区域。

列子

[root@oldboy32-vm1files]# ifconfig eth0 |awk 'NR==2{print $1}'

inet

[root@oldboy32-vm1files]# ifconfig eth0 |awk -F "[ :]+"'NR==2{print $1}'

[root@oldboy32-vm1files]# ifconfig eth0 |awk -F "[ :]+"'NR==2{print $2}'

inet

[root@oldboy32-vm1files]# #awk默认的FS 分隔符空格序列一个空格或多个空格 tab 都认为是一样的一个整体

[root@oldboy32-vm1files]# #[ \t]+

[root@oldboy32-vm1files]# echo -e "\ta\t\tb"

ab

[root@oldboy32-vm1files]# echo -e "\ta\t\tb"|awk '{print $1}'

a

[root@oldboy32-vm1files]# echo -e "\ta\t\tb"|awk '{print $2}'

b

1.15 说明:

这个文件的开头有很多连续的空格,然后才是inet这个字符

当我们使用默认的分隔符的时候,$1是有内容的

当我们指定其他分隔符(费空格),是的时候区域会有所变化

到底为何会这样,我们在这里不在深究,只要了解有这种情况,注意一下就行,因为这个样的结果会仅仅会导致,其余串成一个。

1.16 ORS与OFS简介

OFS与ORS是awk的俩个内置变量

RS是输入记录分隔符,决定awk如何读取或分隔符每行(记录)

ORS表示输出记录分隔符,决定awk如何输出一行(记录)的,默认是回车换行符—(/n)

OFS表示输出区域分隔符,决定awk输出每个区域的时候用什么分隔符

FS表示输入区域分隔符,决定awk输出每个区域的时候用什么分隔符

awk无比强大,可以通过RS,FS,决定awk如何读取数据,也可以通过修改ORS,OFS的值来指定awk如何输出结果。

1.16.1 利用OFS调换ETCpasswd位置

[root@oldboy32-vm1files]# awk'BEGIN{FS=":"}{print $NF,$2,$3,$4,$5,$6,$1}' awkfile.txt

/bin/bashx 0 0 root /root root

/sbin/nologinx 1 1 bin /bin bin

/sbin/nologinx 2 2 daemon /sbin daemon

[root@oldboy32-vm1files]# awk'BEGIN{FS=":";OFS=":"}{print $NF,$2,$3,$4,$5,$6,$1}'awkfile.txt

/bin/bash:x:0:0:root:/root:root

/sbin/nologin:x:1:1:bin:/bin:bin

/sbin/nologin:x:2:2:daemon:/sbin:daemon

1.17 awk都有哪几种模式

1.17.1 正则表达式作为模式

1.17.2 比较表达式作为模式

1.17.3 范围模式

1.17.4 特殊模式BEGIN和END

awk的模式是你学好awk的必备也是最基础的内容,必须熟练掌握

1.18 awk也支持大量的正则表达式,大部分与sed的元字符类似,而且正则表达式是玩转三剑客的必备工具,

以什么开头,精确到列

[root@oldboy32-vm1files]# awk '$3~/c/' count.txt

sync xsync sbin bin sync

uucp xuucp var spool uucp sbin nologin

[root@oldboy32-vm1files]# awk '$3~/c$/' count.txt

sync xsync sbin bin sync

[root@oldboy32-vm1files]# awk '/c$/' count.txt

sync xsync sbin bin sync

[root@oldboy32-vm1files]# awk '$0~/c$/' count.txt

sync xsync sbin bin sync

下面的元字符是AWK的正则表达式符号,基本与sed相同,除了 ( ^ $ ) 他俩有点不i同

元字符

功能

示例

解释

^

字符串开头

/^oldboy/

$3~/^oldboy/

匹配所有以oldboy开头的字符串

匹配出所有第三列中以oldboy开头

$

字符串结尾

/oldbou$/

匹配所有以oldbou结尾的文本(字符串)

匹配第三列中以oldboy结尾的文本

.

匹配任意单个字符(包括回车符)

/o....y/

匹配字母o,然后两个任意字符,再以y结尾的行。如:oldboy,oldddy

*

重复0个或多个前一个字符

/a*cool/

匹配0个或多个a之后紧跟着cool的行,比如:cool,aacool

+

重复前一个字符一次或多次

/a+b/

匹配一个或多个a紧跟着加b的行,如:ab,aaab,aaaaab

重复前一个字符0到1次

/a?b/

匹配0个或1个a,紧跟着b,如:b,ab

[ ]

匹配指定字符组内的任一个字符

/^[abc]/

匹配以字母a或b或c开头的行

[^]

匹配不再指定字符组内的任一个字符

/^[^abc]/

匹配不以字母a或b或c开头的行

( )

子表达式组合

/(cool)+/

表示一个或多个cool组合,当一些字符需要组合一个整体时,使用括号括起来

|

或者的意思

/(cool)|B/

匹配cool或者字母B的行

1.19 说明:

-F 指定分隔符,现在应该知道-F 和FS也是支持正则表达式的了把

[ :]+表示连续的空格或者冒号

-F "[ :]"以连续的空格或者冒号为分隔符

/zhang/表示条件,整行中包Zhang字符的这个条件

{print$1,$(NF-1)} 表示动作,满足条件后,执行显示第一列($1)和倒数第二列($(NF-1) 当然$5也可以。

注意:

NF是一行中有多少列,NF-1 整行就是倒数第二列

$(NF-1)就是取倒数第二列内容

1.20 awk注意事项说明:

awk在输出整行即$0的时候,仅仅是原封不动的输出整行,没有任何修改,这就造成一个问题,如果我修改了OFS,那么输出整行的时候print $0的时候,也不会有任何改变,即:如果awk的action动作没有改行的内容,OFS都不会生效。

所以我们需要让awk知道$0被修改了,这一个事情

$1=$1 是把$1的值赋值给了$1这显然不会修改任何内容,但是这个动作会通知awk我修改了$1的内容,所以再次修改print $0的时候,$0的内容就变化了。

这是一个小技巧、

1.21 awk运算符

awk是一种编程语言,能够进行更为复杂的判断,,当条件为真的时候,awk就会执行相关的action,主要是在针对某一区域做出相关的判断,比如打印成绩在80分以上的行,这样就必须对一个区域做比较判断, awk可以使用的关系运算符,可以用来比较数字者字符串,哈un有正则表达式,当表达式为真的时候,表达式结果为1,否之为0 ,只有表达式为真,awk才执行相关action。

运算符

含义

示例

小于

x>y

<=

小于或等于

x<=y

==

等于

x==y

!=

不等于

x!=y

>.

大于

x>y

>=

大于或等于

x>=y

以上的运算符均是针对数字,下面俩个运算符正对字符串

~

与正则表达式匹配

x~/y/

!~

与正则表达式不匹配

x!~y

第2章 awk特殊模式与END模式

2.1 BEGIN模块

BEGIN模块在awk读取文件之前就执行,一般用来定义我们的内置变量(预定义变量,eg.FSRS)

可以输出表头,(类似excel)表格名称)

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

2.2 命令行 -F本质就是修改的FS变量

2.2.1 第二个作用,在读取文件之前输出些提示性信息,表头。

显示文件awkfile.txt的第一列和第三列(passwd前10行)并在第一行useraanme和UID

[root@zxw files]# awk -F: 'BEGIN{print"useradd","UID"}{print $1 ,$3}'awkfile.txt

useradd UID

root 0

bin 1

daemon 2

adm 3

2.3 awk中的变量的概念简介

直接定义,直接使用即可

awk中字母将会被认为是变量,如果真的要给一个变量赋值字母,(字符串),请使用双引号。

[root@zxwfiles]# awk'BEGIN{abcd=123456;a=abcd;print a}'

123456

[root@zxwfiles]# awk'BEGIN{a=abcd;print a}'

[root@zxwfiles]# awk'BEGIN{a="abcd";print a}'

abcd

2.4 NEGIN模式说明

没有文件awk依旧可以处理BEGIN模式下的动作(命令)

2.5 END模块说明

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

与BEGIN模式相对应的END模块,格式一样,但是END模块仅在awk处理万所有行后才进行处理。

2.6 awk编程思想

2.6.1 先处理,最后在END模式输出

2.6.2 {print NF ,$0} boby 模块处理,处理完毕后

.6.3 END{print"endof file"} 输出一个结果

2.7 awk调试技巧:

让awk显示出每一步的执行结果。

一般通过print来配合完成

2.8 几种常用的运算表达式

c=c+1   >c++

c=c+2   >c+=2

c=c+$0  >c+=$0

2.9 awk中的动作

在一个模式-动作语句中,模式决定动作什么时候执行,有时候动作会非常简单:一条单独的打印

或赋值语句,在有些时候,动作有可能是多条语句,语句之间用换行符或者都好分开。

awk的动作中如果有俩个或者俩个以上的语句,需要用分号分开

动作部分理解为花括号里面的内容即可,总体分为:

1       表达式

2       流程控制语句

3       空语句

4       数组

2.10 awk模式与动作小结

awk命令核心由模式和动作俩部分组成,就是找谁{干啥}

模式就是条件,动作就是具体干什么

1正则表达式

2条件表达式

3范围表达式

注意BEGIN或者END模块只能有一个,BEGIN{}BEGIN{} 或者END{}END{}都是错误的。

找谁干吗模块可以是多个

BEGIN AWK中只能有一个

END awk中只能有一个

他俩可以同时出现

2.11 awk执行过程文字版

1  命令行的赋值(-F或-)

2  执行BEGIN模式里面的内容

3       开始读取文件

4  判断条件(模式)是否成立

成立则执行对应动作里面的内容

读取下一行,循环判断

直到读取到最后一个文件的结尾

5  最后执行END模式里面的内容

5       结束

第3章 awk数组

awk提供了数组来存放一组相关的值

awk是一种编程语言,肯定也支持数组的运用,但是有不同与C语言的数组,数组在awk中被称为关联数据,因为它的下标既可以是数字也可以是字符串,下标通常北称为key,并且与对应的数组元素的值关联,数组元素的key和值都存放在awk程序内部的一张表中,通过一定散列算法来储存,所以数组元素都不是按照顺序相互寻的,打印出来的也肯定不是按序号一定的顺序,但是我们可以通过管道来实现对所需要的数据再次操作来表达自己的效果。

3.1 图片-数组-酒店

老男孩教育酒店

oldboyhotel

酒店里面的几个房间

110oldboyhotel[110]

119oldboyhotel[119]

121oldboyhotel[121]

114oldboyhotel[114]

酒店里面住的客人

101房间住着xiaoyu oldboyhotel[110] ="xiaoyu"

119房间住着ruxueoldboyhotel[119]="ruxue"

120房间住着dandanoldboyhotel[121="dandan"

114房间住着waiwaioldboyhotel[114]="waiwai"

3.2 awk数组小结

pol

in

hotel

变量

关键字

数组名

警察

找人

酒店名称

for循环

for (pol in hotel)

循环(循环 找人  酒店名称)

pol===房间号码===数组元素名字===数组的下标([ ])===门把手

hotel[pol]===GPS定位 ===酒店名称 [房间号码]

hotel [ "b" ]===print  hotel["b"]

3.4 企业面试题数组题分解执行过程

指定分隔符

单引号

创建awk数组(酒店)

取结果

单引号

 

awk -F "[/.]+"

'

{hotel[$2]++}

c++

END{for (pol in hotel)}

print pol , hotel [pol]

'

sort.txt

思路:先处理后输出(END模块输出)

第4章 练习题

4.1 测试文件

[root@zxwfiles]# cat reg.txt

ZhangDandan41117397:250:100:175

ZhangXiaoyu390320151:155:90:201

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

4.1.1.1 第一种

[root@zxw files]# awk -F "[:]+" '/Zhang/{print $1,$2,$6}' reg.txt

Zhang Dandan 175

Zhang Xiaoyu 201

4.1.1.2 第二种

[root@oldboy32-vm1files]# awk -F "[ :]+" '/^Zhang/' reg.txt

ZhangDandan41117397:250:100:175

ZhangXiaoyu390320151:155:90:201

4.1.1.3 第三种

[root@oldboy32-vm1files]# awk -F "[ :]+" '$0~/^Zhang/' reg.txt

ZhangDandan41117397:250:100:175

ZhangXiaoyu390320151:155:90:201

4.1.1.4 第四种

[root@oldboy32-vm1files]# awk -F "[ :]+" '/^Zhang/{print$2,$5}' reg.txt

Dandan100

Xiaoyu90

4.1.1.5 注意错误1

[root@oldboy32-vm1files]# awk -F "[ :]+" '/^Zhang/{print$2,$NF-1}' reg.txt

Dandan174

Xiaoyu200

4.1.1.6 注意错误2

[root@oldboy32-vm1files]# awk -F "[ :]+" '/^Zhang/{print$2,$(NF-1)}' reg.txt

Dandan100

Xiaoyu90

4.1.2 显示Xiaoyu的名字和ID号码

[root@zxwfiles]# awk -F "[ :]+" '/Xiaoyu/{print$1,$2,$3}' reg.txt

ZhangXiaoyu 390320151

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

[root@zxwfiles]# awk -F "[ :]+" '$3~/^41/ {print $1 $2$3}' reg.txt

ZhangDandan41117397

LiuBingbing41117483

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

[root@zxwfiles]# awk -F "[ :]+" '$2~/^D|^X/{print$1,$2}' reg.txt

ZhangDandan

ZhangXiaoyu

WangXiaoai

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

[root@zxwfiles]# awk -F "[ :]+" '$3~/1$|5$/{print$1,$2}' reg.txt

ZhangXiaoyu

WuWaiwai

WangXiaoai

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

4.1.6.1 第一种

[root@zxwfiles]# awk'BEGIN {FS=":" ; OFS="$"} {print "$",$2,$3,$4}' reg.txt

250$100$175

155$90$201

250$60$50

4.1.6.2 第二种

[root@oldboy32-vm1files]# awk '$2~/^Xiaoyu$/{print $NF}' reg.txt

:155:90:201

[root@oldboy32-vm1files]# awk '$2~/^Xiaoyu$/{print $NF}' reg.txt |tr":" "$"

$155$90$201

[root@oldboy32-vm1files]# #sub gsub gensub

[root@oldboy32-vm1files]# #gsub

[root@oldboy32-vm1files]# #gsub(r, s [, t])

[root@oldboy32-vm1files]# #函数

[root@oldboy32-vm1files]# #gsub(正则表达式,你要替换成啥[,目标($1 $2 $3)])

[root@oldboy32-vm1files]# awk '$2~/^Xiaoyu$/{gsub(/:/,"$")}'reg.txt

[root@oldboy32-vm1files]# awk'$2~/^Xiaoyu$/{gsub(/:/,"$");print $NF}' reg.txt

$155$90$201

[root@oldboy32-vm1files]# awk'$2~/^Xiaoyu$/{gsub(/:/,"$",$NF);print $NF}' reg.txt

$155$90$201

4.1.6.3 第三种

awk'BEGIN {FS=":";OFS="$"}{print "",$2,$3,$4}' reg.txt

4.1.6.4 疑问(下面$0和$1,$2,$3)输出的结果为啥不一样

[root@oldboy32-vm1 files]#awk -F : -v OFS="$"'{print $0}' reg.txt

ZhangDandan41117397:250:100:175

ZhangXiaoyu390320151:155:90:201

MengFeixue80042789:250:60:50

[root@oldboy32-vm1files]# awk -F : -v OFS="$"'{print $1,$2,$3}' reg.txt

ZhangDandan41117397$250$100

ZhangXiaoyu390320151$155$90

LaoNanhai918391635$250$100

XManX10000$999$999

[root@oldboy32-vm1files]# awk -F : -v OFS="$"'{print $1,$2,$3,$4}' reg.txt

ZhangDandan41117397$250$100$175

ZhangXiaoyu390320151$155$90$201

MengFeixue80042789$250$60$50

[root@oldboy32-vm1files]# awk -F : -v OFS="$"'{$1=$1;print $0}' reg.txt

ZhangDandan41117397$250$100$175

ZhangXiaoyu390320151$155$90$201

LiYoujiu918391635$175$75$300

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

[root@zxwfiles]# awk'BEGIN {FS="[ ]+";OFS=","}{print $2,$1}' reg.txt

Dandan,Zhang

Xiaoyu,Zhang

Feixue,Meng

4.2 正则表达式部分的疑问

[root@demon files]# awk '/^Xiaoyu/' /server/files/reg.txt

[root@demon files]# awk '$2~/^Xiaoyu/' /server/files/reg.txt

/^Xiaoyu/的意思不是以Xiaoyu为开头的字符串吗,为什么默认$0匹配就不行了?

/Xiaoyu/这样就可以了,这是为什么?

解答:

awk不会自动匹配,需要明确告诉它是那一列

^          matches the beginning of astring.  #匹配字符串的开头的位置

$          matches the end of a string.        #匹配字符串结尾的位置

awk '/^Xiaoyu/' /server/files/reg.txt

awk '/Xiaoyu/' /server/files/reg.txt

grep "^Xiaoyu" reg.txt

grep "Xiaoyu" reg.txt

4.3 匹配除了含有oldboy的其他行

4.3.1 测试文件

[root@zxw files]# cat test.txt

lidao

oldboy

oldboylinux

zhangdao

xiadao

[root@zxw files]#

4.3.2 注意精确

[root@oldboy32-vm1files]# awk '/^l|z|x|x$/' test.txt

lidao

oldboylinux

zhangdao

[root@oldboy32-vm1files]# egrep "^l|z|x|x$" test.txt

lidao

oldboylinux

zhangdao

[root@oldboy32-vm1files]# egrep "^l|x$|^z|^x" test.txt

lidao

oldboylinux

zhangdao

4.4 表示一个范围,与sed(2,5p)意思相近

[root@oldboy32-vm1files]# awk 'NR==2,NR==5' awkfile.txt

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

[root@oldboy32-vm1files]# #范围条件/范围模式

4.5 BEGIN在读取文件以前执行

[root@oldboy32-vm1files]# awk 'BEGIN{print 3/10}'

0.3

[root@oldboy32-vm1files]# awk 'BEGIN{print 10/3}'

3.33333

4.6 a=1  输出1 a=lidao  awk会将lidao(英文字母)认为是一个变量(需要加“”)

[root@oldboy32-vm1files]# awk 'BEGIN{a=1;print a}'

1

[root@oldboy32-vm1files]# awk 'BEGIN{a=lidao;print a}'

[root@oldboy32-vm1files]# awk 'BEGIN{a="";print a}'

[root@oldboy32-vm1files]# awk 'BEGIN{a="lidao";print a}'

lidao

4.7 END模式

[root@oldboy32-vm1 files]# awk'BEGIN{print "name","ID"}{print $2,$3}END{print"hello" }' reg.txt

name ID

Dandan 41117397

Xiaoyu 390320151

Feixue 80042789

hello

4.8 awk调试过程

[root@oldboy32-vm1~]# awk '/^$/{notepad++}END{print notepad}'/etc/services16

[root@oldboy32-vm1~]# awk '/^$/{notepad++;print notepad}'/etc/services

1

2

3

4.9 数组

[root@oldboy32-vm1~]# awk'BEGIN{hotel[110]="xiaoyu";hotel[114]="xiadao";

hotel[121]="dandan"

hotel[119]="waiwai"

print hotel[110],hotel[114],hotel[119],hotel[121]}'

xiaoyuxiadao waiwai dandan

[root@oldboy32-vm1~]# awk'BEGIN{hotel[110]="xiaoyu";hotel[114]="xiadao";

hotel[121]="dandan"

hotel[119]="waiwai"

for(pol in hotel )print pol,hotel[pol]}'

110xiaoyu

121dandan

114xiadao

119waiwai

数组

[root@zxw~]# awk 'BEGIN{hotel[100]="zxw";hotel[200]="mzl";hotel[300]="wyf";hotel[400]="yz";for(abc in hotel)print abc,hotel[abc]}'

100 zxw

200 mzl

300 wyf

400 yz

第5章 企业案例

5.1 企业面试题: 按单词出现频率降序排序(计算文件中每个单词的重复数量)

注:(此处使用sort与uniq即可)

[root@oldboy32-vm1files]# #sort 默认是按照字母顺序排列

awk -vRS=" " '{print $0}' count.txt|xargs -n1|sort|uniq -c|sort -nr

awk -vRS=" " '{print $0}' count.txt|sort|uniq -c|sort -nr

5.1.1 按字母查找

awk 'BEGIN{RS="[:0-9/ ]+"}{printNR,$0}' awkfile.txt

awk 'BEGIN{RS="[^a-zA-Z]+"}{printNR,$0}' awkfile.txt

[root@zxwfiles]# awk 'BEGIN{RS=":|/|[0-9]"}{print $0}' awkfile.txt|sort|uniq-c|sort -rn

5.2 考试题1:处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)

oldboy.log

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

5.2.1 答案:

[root@zxwfiles]# awk 'BEGIN{FS="."}{print$3}' oldboy.txt|sort|uniq -c |sort -rn

3 org/index

1 org/3

1 org/2

1 org/1

[root@zxwfiles]#

5.3 【企业面试题】处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)

[root@zxwfiles]# cat oldboy.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@zxwfiles]#

5.3.1 答案:

[root@oldboy32-vm1files]# awk -F "[/.]+" '{h[$2]++;print$2,h["www"]}' url.txt

www 1

www 2

post 2

mp3 2

www 3

post 3

[root@oldboy32-vm1files]# awk -F "[/.]+" '{h[$2]++;print$2,h["www"]}' url.txt

[root@oldboy32-vm1files]# awk -F "[/.]+" '{h[$2]++;print$2,h[""]}' url.txt

[root@oldboy32-vm1files]# awk -F "[/.]+" '{h[$2]++;print$2,h["post"]}' url.txt

[root@oldboy32-vm1files]# awk -F "[/.]+" '{h[$2]++;print$2,h[$2]}' url.txt

[root@oldboy32-vm1files]# awk -F "[/.]+" '{h[$2]++}END{for(polin h) print pol,h[pol]}' url.txt

www 3

mp3 1

post 2

[root@oldboy32-vm1files]# awk -F "[/]+" '{h[$2]++}END{for(polin h) print pol,h[pol]}' url.txt

mp3.etiantian.org1

post.etiantian.org2

www.etiantian.org3

5.3.2 方法一

awk -v RS="[^a-zA-Z]+"'{h[$0]++}END{for(pol in h)print pol,h[pol]}' awkfile.txt |sort-rnk2|column -t

5.3.3 方法二

awk'BEGIN{RS="[^a-zA-Z]+"}{h[$0]++}END{for(pol in h)printpol,h[pol]}' awkfile.txt |sort -rnk2|column -t

本文出自 “11845753” 博客,转载请与作者联系!

目录

awk课程总结... 1

第1章 awk基础入门... 1

1.1 awk基础入门... 1

1.2 awk简介... 1

1.2.1 一种名字怪异的语言... 1

1.2.2 模式扫描和处理... 1

1.3 学过awk可以掌握的内容... 1

1.4 awk命令... 1

1.5模式及pattern,可以类似理解成sed的模式匹配,可以由表达式组成,也可以是俩个正斜杠之间的正则表达式,比如:NR==1 ,这就是模式,可以理解为一个条件。... 2

1.6动作即action,是由在大括号里面的一条或者多条语句组成,语句之间使用分号隔开,如下awk使用格式... 2

1.7 awk执行过程... 2

1.8 接下来说俩个新概念:记录和字段,这里为了方便理解可以把记录当做行记录===行,字段相当于列,字段===列。... 3

1.9 awk记录分隔符 -RS. 3

1.9.1 awk默认情况下每一行都是一个记录... 3

1.9.2 RS即record separator输入数据记录分隔符,每一行是怎么来的,表示每个记录输入的时候的分隔符,即行与行之间如何分割。... 3

1.9.3 NR即number of record 记录行号,表示当前正在处理的行的号码... 5

1.9.4 ORS即output record separator 输出记录分隔符。... 5

1.9.5 awk使用内置变量RS来存放输入记录分隔符,RS表示的是输入的记录分隔符,这个值可以通过BEGIN模块重新定义修改。... 5

1.10 思路... 5

1.11 awk记录知识小结... 6

1.11.1 NR存放着每个记录的号(行号),读取新行时候会自动加1(+1)... 6

1.11.2 RS是输入数据的记录的分隔符,简单理解就是可以指定每个记录的结尾标致... 6

1.11.3 RS作用就是表示一个记录的结束... 6

1.11.4 当我们修改了RS的值,最好配合NR来查看变化,也就是修改了RS的值通过NR查看结果,调试awk程序。... 6

1.11.5 ORS输出数据的记录的分隔符... 6

1.12 awk学习技巧一则... 6

1.13 字段(字段)... 6

1.14 FS. 7

1.15 说明:... 7

1.16 ORS与OFS简介... 8

1.16.1 利用OFS调换ETCpasswd位置... 8

1.17 awk都有哪几种模式... 9

1.17.1 正则表达式作为模式... 9

1.17.2 比较表达式作为模式... 9

1.17.3 范围模式... 9

1.17.4 特殊模式BEGIN和END.. 9

1.18 awk也支持大量的正则表达式,大部分与sed的元字符类似,而且正则表达式是玩转三剑客的必备工具,... 9

1.19 说明:... 10

1.20 awk注意事项说明:... 10

1.21 awk运算符... 10

第2章 awk特殊模式与END模式... 11

2.1 BEGIN模块... 11

2.2 命令行 -F本质就是修改的FS变量... 11

2.2.1 第二个作用,在读取文件之前输出些提示性信息,表头。... 11

2.3 awk中的变量的概念简介... 12

2.4 NEGIN模式说明... 12

2.5 END模块说明... 12

2.6 awk编程思想... 12

2.6.1 先处理,最后在END模式输出... 12

2.6.2 {print NF ,$0} boby 模块处理,处理完毕后... 12

2.6.3 END{print"end of file"} 输出一个结果... 12

2.7 awk调试技巧:... 12

2.8 几种常用的运算表达式... 12

2.9 awk中的动作... 13

2.10 awk模式与动作小结... 13

2.11 awk执行过程文字版... 13

第3章 awk数组... 14

3.1 图片-数组-酒店... 14

3.2 awk数组小结... 15

3.3 这个不知道起什么名... 15

3.4 企业面试题数组题分解执行过程... 16

第4章练习题... 16

4.1 测试文件... 16

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

4.1.2 显示Xiaoyu的名字和ID号码... 17

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

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

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

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

4.2 正则表达式部分的疑问... 20

4.3 匹配除了含有oldboy的其他行... 20

4.3.1 测试文件... 20

4.3.2 注意精确... 21

4.4 表示一个范围,与sed(2,5p)意思相近... 21

4.5 BEGIN在读取文件以前执行... 21

4.6 a=1输出1a=lidaoawk会将lidao(英文字母)认为是一个变量(需要加“”)... 21

4.7 END模式... 22

4.8 awk调试过程... 22

4.9 数组... 23

第5章企业案例... 23

5.1 企业面试题: 按单词出现频率降序排序(计算文件中每个单词的重复数量)... 23

5.1.1 按字母查找... 24

5.2 考试题1:处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)24

5.2.1 答案:... 24

5.3 【】企业面试题】处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)24

5.3.1 答案:... 25

5.3.2 方法一... 26

5.3.3 方法二... 26

awk课程总结

第1章 awk基础入门

要弄懂awk程序,必须熟悉了解这个工具的规则,

1.2 awk简介

1.2.1 一种名字怪异的语言

1.2.2 模式扫描和处理

awk不仅仅是Linux中的一个命令,而且是一种编程语言,可以用来处理数据和生成报告,处理的数据可以是一个或者多个文件,可以是来自标准输入,也可以是通过管道获取标准输入,awk可以在命令行上直接编辑命令进行操作,也可以编写成awk程序来进行运用,本章主要讲解awk命令行的运用,较为复杂的程序会包含在以后的课程中

  回顾sed命令,把文件当做流水一样处理

1.3 学过awk可以掌握的内容

 1记录和字段

 2 模式匹配:模式与动作

 3 基本的awk执行过程

 4awk常用的内置变量(预定义变量)

 5 awk数组(工作常用的)

 6awk语法:循环,条件

 7awk常用的函数

 8 向awk传递参数

 9awk引用shell变量

10 awk小程序及调试思路

1.4 awk命令

awk -v RS=":"  与‘BEGIN{RS=":"}’一样

uniq 合并相同行    -c  将相同行相加输出

sort  排序, 默认按照字母顺序排序   -r 逆向排序     -n  排序

culomn -t      使行,列对齐

awk的默认的FS 分隔符 空格序列  TAB键 一个或者多个空格 ,都认为是一个整体

OFS不支持正则表达式

FS=-F  指定分隔符

posix   使awk支持扩展正则表达式,如:'/0{2,3}/'

awk中  $N==root    要写成$N=="root"   如果不佳双引号,awk会把等于看成是一个变量

例子:

[root@oldboy32-vm1~]# awk -F ":"'NR<=5{print $1,$3}' /etc/passwd

root 0

bin 1#awk 参数 '条件(找谁){动作(干啥)}' /etc/passwd

1.5 模式及pattern,可以类似理解成sed的模式匹配,可以由表达式组成,也可以是俩个正斜杠之间的正则表达式,比如:NR==1,这就是模式,可以理解为一个条件。

1.6 动作即action,是由在大括号里面的一条或者多条语句组成,语句之间使用分号隔开,如下awk使用格式

awk处理的内容可以来自标准输入(>),一个或者多个文本或管道

模式动作里面分俩部分,大括号外面的叫找谁里面的叫干啥

1.7 awk执行过程

1 首先读取一行

2 模式是我要处理的行吗?

3 如果是,则对读入行执行动作里的命令

4 如果否,则重复上面的过程直到最后一个文件结尾

5 END模块

6 结束

1.8 接下来说俩个新概念:记录和字段,这里为了方便理解可以把记录当做行记录===行,字段相当于列,字段===列。

record

记录 ,行

field

域,区域,字段,列

1.9 awk记录分隔符 -RS

记录分隔符 -每一个记录是如何结束的

[root@zxw files]# cat reg.txt

Zhang (FS)Dandan41117397:250:100:175$0

RS

Zhang (FS)Xiaoyu390320151:155:90:201$0

RS

Meng(FS)Feixue80042789:250:60:50$0

RS

1.9.1 awk默认情况下每一行都是一个记录

1.9.2 RS即record separator输入数据记录分隔符,每一行是怎么来的,表示每个记录输入的时候的分隔符,即行与行之间如何分割。

例子:

awk指定RS分割符号:

[root@oldboy32-vm1files]# head -2 awkfile.txt

root:x:0:0:root:/root:/bin/bash

bin:x:1:1:bin:/bin:/sbin/nologin

[root@oldboy32-vm1files]# awk 'BEGIN{RS="/"}{print NR,$0}' awkfile.txt

1root:x:0:0:root:

2 root:

3 bin

4 bash

1.9.3 NR即number of record 记录行号,表示当前正在处理的行的号码

取oldboy

[root@oldboy32-vm1files]# echo "I am oldboy,my qq is31333741">>/server/files/oldboy.txt

[root@oldboy32-vm1files]# cat oldboy.txt

I am oldboy,myqq is 31333741

[root@oldboy32-vm1files]# echo oldboy,31333741

oldboy,31333741

[root@oldboy32-vm1files]# awk -F " |," '{print $3,$NF}'oldboy.txt

oldboy31333741

[root@oldboy32-vm1files]# awk -F " |," '{print$3","$NF}' oldboy.txt

oldboy,31333741

[root@oldboy32-vm1files]# awk -F "[ ,]" '{print$3","$NF}' oldboy.txt

oldboy,31333741

1.9.4 ORS即output record separator 输出记录分隔符。

1.9.5 awk使用内置变量RS来存放输入记录分隔符,RS表示的是输入的记录分隔符,这个值可以通过BEGIN模块重新定义修改。

1.10 思路

1 让所有的单词排成一列,这样每个单词都是单独的一行

2 设置RS的值为空格

3 将文件里面的所有空格替换为回车换行符“\n”

4 grep所有连续的字母,grep -o 参数让他们排成一排

整体思路 :想办法让所有单词排成一行,站成一队,排序,合并重复的,显示重复数量

1.11 awk记录知识小结

1.11.1 NR存放着每个记录的号(行号),读取新行时候会自动加1(+1)

1.11.2 RS是输入数据的记录的分隔符,简单理解就是可以指定每个记录的结尾标致

1.11.3 RS作用就是表示一个记录的结束

1.11.4 当我们修改了RS的值,最好配合NR来查看变化,也就是修改了RS的值通过NR查看结果,调试awk程序。

1.11.5 ORS输出数据的记录的分隔符

ORS

[root@oldboy32-vm1files]# cat ors.txt

a

b

c

[root@oldboy32-vm1files]# awk 'BEGIN{ORS="oldboy"}{print $0}'ors.txt

aoldboyboldboycoldboy[root@oldboy32-vm1files]#

1.12 awk学习技巧一则

大象放冰箱分几步?  打开冰箱门,把大象放进去,关上冰箱门。awk也是一样,一步一步来,先修改RS,然后用NR调试,看看到底如何分割的,然后通过sort排序,uniq去掉重复的。

1.13 字段(字段)

每条记录都是由多个区域组成的,默认情况下区域之间的分隔符是由空格(即空格或者制表符)来分割,并且将分隔符记录在内置变量FS中每行记录的区域数据保存在awk的内置变量NF中

约定:

      field有很多多种解释,域,记录,区域,为了方便理解统一使用区域表示field。

Zhang (FS)Dandan41117397:250:100:175$0

RS

Zhang (FS)Xiaoyu390320151:155:90:201$0

RS

Meng (FS) Feixue80042789:250:60:50$0

RS

Wu(FS)Waiwai70271111:250:80:75$0

RS

Liu(FS)Bingbing41117483:250:100:175   $0

RS

Wang(FS)Xiaoai3515064655:50:95:135  $0

RS

Zi(FS)Gege1986787350:250:168:200   $0

1.14 FS

FS即field separator,输入字段(列)分隔符,分隔符就是菜刀,把一行字符串切为很多个区域。

NF即number offields ,表示一行中列的个数,可以理解为菜刀切过一行后,切成了多少份,OFS输出字段(列)分隔符

awk使用内置变量FS来记录区域分隔符的内容,FS可以在命令行上通过 F 参数来更改,也艺客通过BEGIN模块来更改。

然后通过$n ,n是整数,来取北切割后的区域,$1取第一个区域,$2取第二个区域,$NF取最后一个区域。

列子

[root@oldboy32-vm1files]# ifconfig eth0 |awk 'NR==2{print $1}'

inet

[root@oldboy32-vm1files]# ifconfig eth0 |awk -F "[ :]+"'NR==2{print $1}'

[root@oldboy32-vm1files]# ifconfig eth0 |awk -F "[ :]+"'NR==2{print $2}'

inet

[root@oldboy32-vm1files]# #awk默认的FS 分隔符空格序列一个空格或多个空格 tab 都认为是一样的一个整体

[root@oldboy32-vm1files]# #[ \t]+

[root@oldboy32-vm1files]# echo -e "\ta\t\tb"

ab

[root@oldboy32-vm1files]# echo -e "\ta\t\tb"|awk '{print $1}'

a

[root@oldboy32-vm1files]# echo -e "\ta\t\tb"|awk '{print $2}'

b

1.15 说明:

这个文件的开头有很多连续的空格,然后才是inet这个字符

当我们使用默认的分隔符的时候,$1是有内容的

当我们指定其他分隔符(费空格),是的时候区域会有所变化

到底为何会这样,我们在这里不在深究,只要了解有这种情况,注意一下就行,因为这个样的结果会仅仅会导致,其余串成一个。

1.16 ORS与OFS简介

OFS与ORS是awk的俩个内置变量

RS是输入记录分隔符,决定awk如何读取或分隔符每行(记录)

ORS表示输出记录分隔符,决定awk如何输出一行(记录)的,默认是回车换行符—(/n)

OFS表示输出区域分隔符,决定awk输出每个区域的时候用什么分隔符

FS表示输入区域分隔符,决定awk输出每个区域的时候用什么分隔符

awk无比强大,可以通过RS,FS,决定awk如何读取数据,也可以通过修改ORS,OFS的值来指定awk如何输出结果。

1.16.1 利用OFS调换ETCpasswd位置

[root@oldboy32-vm1files]# awk'BEGIN{FS=":"}{print $NF,$2,$3,$4,$5,$6,$1}' awkfile.txt

/bin/bashx 0 0 root /root root

/sbin/nologinx 1 1 bin /bin bin

/sbin/nologinx 2 2 daemon /sbin daemon

[root@oldboy32-vm1files]# awk'BEGIN{FS=":";OFS=":"}{print $NF,$2,$3,$4,$5,$6,$1}'awkfile.txt

/bin/bash:x:0:0:root:/root:root

/sbin/nologin:x:1:1:bin:/bin:bin

/sbin/nologin:x:2:2:daemon:/sbin:daemon

1.17 awk都有哪几种模式

1.17.1 正则表达式作为模式

1.17.2 比较表达式作为模式

1.17.3 范围模式

1.17.4 特殊模式BEGIN和END

awk的模式是你学好awk的必备也是最基础的内容,必须熟练掌握

1.18 awk也支持大量的正则表达式,大部分与sed的元字符类似,而且正则表达式是玩转三剑客的必备工具,

以什么开头,精确到列

[root@oldboy32-vm1files]# awk '$3~/c/' count.txt

sync xsync sbin bin sync

uucp xuucp var spool uucp sbin nologin

[root@oldboy32-vm1files]# awk '$3~/c$/' count.txt

sync xsync sbin bin sync

[root@oldboy32-vm1files]# awk '/c$/' count.txt

sync xsync sbin bin sync

[root@oldboy32-vm1files]# awk '$0~/c$/' count.txt

sync xsync sbin bin sync

下面的元字符是AWK的正则表达式符号,基本与sed相同,除了 ( ^ $ ) 他俩有点不i同

元字符

功能

示例

解释

^

字符串开头

/^oldboy/

$3~/^oldboy/

匹配所有以oldboy开头的字符串

匹配出所有第三列中以oldboy开头

$

字符串结尾

/oldbou$/

匹配所有以oldbou结尾的文本(字符串)

匹配第三列中以oldboy结尾的文本

.

匹配任意单个字符(包括回车符)

/o....y/

匹配字母o,然后两个任意字符,再以y结尾的行。如:oldboy,oldddy

*

重复0个或多个前一个字符

/a*cool/

匹配0个或多个a之后紧跟着cool的行,比如:cool,aacool

+

重复前一个字符一次或多次

/a+b/

匹配一个或多个a紧跟着加b的行,如:ab,aaab,aaaaab

重复前一个字符0到1次

/a?b/

匹配0个或1个a,紧跟着b,如:b,ab

[ ]

匹配指定字符组内的任一个字符

/^[abc]/

匹配以字母a或b或c开头的行

[^]

匹配不再指定字符组内的任一个字符

/^[^abc]/

匹配不以字母a或b或c开头的行

( )

子表达式组合

/(cool)+/

表示一个或多个cool组合,当一些字符需要组合一个整体时,使用括号括起来

|

或者的意思

/(cool)|B/

匹配cool或者字母B的行

1.19 说明:

-F 指定分隔符,现在应该知道-F 和FS也是支持正则表达式的了把

[ :]+表示连续的空格或者冒号

-F "[ :]"以连续的空格或者冒号为分隔符

/zhang/表示条件,整行中包Zhang字符的这个条件

{print$1,$(NF-1)} 表示动作,满足条件后,执行显示第一列($1)和倒数第二列($(NF-1) 当然$5也可以。

注意:

NF是一行中有多少列,NF-1 整行就是倒数第二列

$(NF-1)就是取倒数第二列内容

1.20 awk注意事项说明:

awk在输出整行即$0的时候,仅仅是原封不动的输出整行,没有任何修改,这就造成一个问题,如果我修改了OFS,那么输出整行的时候print $0的时候,也不会有任何改变,即:如果awk的action动作没有改行的内容,OFS都不会生效。

所以我们需要让awk知道$0被修改了,这一个事情

$1=$1 是把$1的值赋值给了$1这显然不会修改任何内容,但是这个动作会通知awk我修改了$1的内容,所以再次修改print $0的时候,$0的内容就变化了。

这是一个小技巧、

1.21 awk运算符

awk是一种编程语言,能够进行更为复杂的判断,,当条件为真的时候,awk就会执行相关的action,主要是在针对某一区域做出相关的判断,比如打印成绩在80分以上的行,这样就必须对一个区域做比较判断, awk可以使用的关系运算符,可以用来比较数字者字符串,哈un有正则表达式,当表达式为真的时候,表达式结果为1,否之为0 ,只有表达式为真,awk才执行相关action。

运算符

含义

示例

小于

x>y

<=

小于或等于

x<=y

==

等于

x==y

!=

不等于

x!=y

>.

大于

x>y

>=

大于或等于

x>=y

以上的运算符均是针对数字,下面俩个运算符正对字符串

~

与正则表达式匹配

x~/y/

!~

与正则表达式不匹配

x!~y

第2章 awk特殊模式与END模式

2.1 BEGIN模块

BEGIN模块在awk读取文件之前就执行,一般用来定义我们的内置变量(预定义变量,eg.FSRS)

可以输出表头,(类似excel)表格名称)

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

2.2 命令行 -F本质就是修改的FS变量

2.2.1 第二个作用,在读取文件之前输出些提示性信息,表头。

显示文件awkfile.txt的第一列和第三列(passwd前10行)并在第一行useraanme和UID

[root@zxw files]# awk -F: 'BEGIN{print"useradd","UID"}{print $1 ,$3}'awkfile.txt

useradd UID

root 0

bin 1

daemon 2

adm 3

2.3 awk中的变量的概念简介

直接定义,直接使用即可

awk中字母将会被认为是变量,如果真的要给一个变量赋值字母,(字符串),请使用双引号。

[root@zxwfiles]# awk'BEGIN{abcd=123456;a=abcd;print a}'

123456

[root@zxwfiles]# awk'BEGIN{a=abcd;print a}'

[root@zxwfiles]# awk'BEGIN{a="abcd";print a}'

abcd

2.4 NEGIN模式说明

没有文件awk依旧可以处理BEGIN模式下的动作(命令)

2.5 END模块说明

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

与BEGIN模式相对应的END模块,格式一样,但是END模块仅在awk处理万所有行后才进行处理。

2.6 awk编程思想

2.6.1 先处理,最后在END模式输出

2.6.2 {print NF ,$0} boby 模块处理,处理完毕后

.6.3 END{print"endof file"} 输出一个结果

2.7 awk调试技巧:

让awk显示出每一步的执行结果。

一般通过print来配合完成

2.8 几种常用的运算表达式

c=c+1   >c++

c=c+2   >c+=2

c=c+$0  >c+=$0

2.9 awk中的动作

在一个模式-动作语句中,模式决定动作什么时候执行,有时候动作会非常简单:一条单独的打印

或赋值语句,在有些时候,动作有可能是多条语句,语句之间用换行符或者都好分开。

awk的动作中如果有俩个或者俩个以上的语句,需要用分号分开

动作部分理解为花括号里面的内容即可,总体分为:

1       表达式

2       流程控制语句

3       空语句

4       数组

2.10 awk模式与动作小结

awk命令核心由模式和动作俩部分组成,就是找谁{干啥}

模式就是条件,动作就是具体干什么

1正则表达式

2条件表达式

3范围表达式

注意BEGIN或者END模块只能有一个,BEGIN{}BEGIN{} 或者END{}END{}都是错误的。

找谁干吗模块可以是多个

BEGIN AWK中只能有一个

END awk中只能有一个

他俩可以同时出现

2.11 awk执行过程文字版

1  命令行的赋值(-F或-)

2  执行BEGIN模式里面的内容

3       开始读取文件

4  判断条件(模式)是否成立

成立则执行对应动作里面的内容

读取下一行,循环判断

直到读取到最后一个文件的结尾

5  最后执行END模式里面的内容

5       结束

第3章 awk数组

awk提供了数组来存放一组相关的值

awk是一种编程语言,肯定也支持数组的运用,但是有不同与C语言的数组,数组在awk中被称为关联数据,因为它的下标既可以是数字也可以是字符串,下标通常北称为key,并且与对应的数组元素的值关联,数组元素的key和值都存放在awk程序内部的一张表中,通过一定散列算法来储存,所以数组元素都不是按照顺序相互寻的,打印出来的也肯定不是按序号一定的顺序,但是我们可以通过管道来实现对所需要的数据再次操作来表达自己的效果。

3.1 图片-数组-酒店

老男孩教育酒店

oldboyhotel

酒店里面的几个房间

110oldboyhotel[110]

119oldboyhotel[119]

121oldboyhotel[121]

114oldboyhotel[114]

酒店里面住的客人

101房间住着xiaoyu oldboyhotel[110] ="xiaoyu"

119房间住着ruxueoldboyhotel[119]="ruxue"

120房间住着dandanoldboyhotel[121="dandan"

114房间住着waiwaioldboyhotel[114]="waiwai"

3.2 awk数组小结

pol

in

hotel

变量

关键字

数组名

警察

找人

酒店名称

for循环

for (pol in hotel)

循环(循环 找人  酒店名称)

pol===房间号码===数组元素名字===数组的下标([ ])===门把手

hotel[pol]===GPS定位 ===酒店名称 [房间号码]

hotel [ "b" ]===print  hotel["b"]

3.4 企业面试题数组题分解执行过程

指定分隔符

单引号

创建awk数组(酒店)

取结果

单引号

 

awk -F "[/.]+"

'

{hotel[$2]++}

c++

END{for (pol in hotel)}

print pol , hotel [pol]

'

sort.txt

思路:先处理后输出(END模块输出)

第4章 练习题

4.1 测试文件

[root@zxwfiles]# cat reg.txt

ZhangDandan41117397:250:100:175

ZhangXiaoyu390320151:155:90:201

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

4.1.1.1 第一种

[root@zxw files]# awk -F "[:]+" '/Zhang/{print $1,$2,$6}' reg.txt

Zhang Dandan 175

Zhang Xiaoyu 201

4.1.1.2 第二种

[root@oldboy32-vm1files]# awk -F "[ :]+" '/^Zhang/' reg.txt

ZhangDandan41117397:250:100:175

ZhangXiaoyu390320151:155:90:201

4.1.1.3 第三种

[root@oldboy32-vm1files]# awk -F "[ :]+" '$0~/^Zhang/' reg.txt

ZhangDandan41117397:250:100:175

ZhangXiaoyu390320151:155:90:201

4.1.1.4 第四种

[root@oldboy32-vm1files]# awk -F "[ :]+" '/^Zhang/{print$2,$5}' reg.txt

Dandan100

Xiaoyu90

4.1.1.5 注意错误1

[root@oldboy32-vm1files]# awk -F "[ :]+" '/^Zhang/{print$2,$NF-1}' reg.txt

Dandan174

Xiaoyu200

4.1.1.6 注意错误2

[root@oldboy32-vm1files]# awk -F "[ :]+" '/^Zhang/{print$2,$(NF-1)}' reg.txt

Dandan100

Xiaoyu90

4.1.2 显示Xiaoyu的名字和ID号码

[root@zxwfiles]# awk -F "[ :]+" '/Xiaoyu/{print$1,$2,$3}' reg.txt

ZhangXiaoyu 390320151

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

[root@zxwfiles]# awk -F "[ :]+" '$3~/^41/ {print $1 $2$3}' reg.txt

ZhangDandan41117397

LiuBingbing41117483

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

[root@zxwfiles]# awk -F "[ :]+" '$2~/^D|^X/{print$1,$2}' reg.txt

ZhangDandan

ZhangXiaoyu

WangXiaoai

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

[root@zxwfiles]# awk -F "[ :]+" '$3~/1$|5$/{print$1,$2}' reg.txt

ZhangXiaoyu

WuWaiwai

WangXiaoai

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

4.1.6.1 第一种

[root@zxwfiles]# awk'BEGIN {FS=":" ; OFS="$"} {print "$",$2,$3,$4}' reg.txt

250$100$175

155$90$201

250$60$50

4.1.6.2 第二种

[root@oldboy32-vm1files]# awk '$2~/^Xiaoyu$/{print $NF}' reg.txt

:155:90:201

[root@oldboy32-vm1files]# awk '$2~/^Xiaoyu$/{print $NF}' reg.txt |tr":" "$"

$155$90$201

[root@oldboy32-vm1files]# #sub gsub gensub

[root@oldboy32-vm1files]# #gsub

[root@oldboy32-vm1files]# #gsub(r, s [, t])

[root@oldboy32-vm1files]# #函数

[root@oldboy32-vm1files]# #gsub(正则表达式,你要替换成啥[,目标($1 $2 $3)])

[root@oldboy32-vm1files]# awk '$2~/^Xiaoyu$/{gsub(/:/,"$")}'reg.txt

[root@oldboy32-vm1files]# awk'$2~/^Xiaoyu$/{gsub(/:/,"$");print $NF}' reg.txt

$155$90$201

[root@oldboy32-vm1files]# awk'$2~/^Xiaoyu$/{gsub(/:/,"$",$NF);print $NF}' reg.txt

$155$90$201

4.1.6.3 第三种

awk'BEGIN {FS=":";OFS="$"}{print "",$2,$3,$4}' reg.txt

4.1.6.4 疑问(下面$0和$1,$2,$3)输出的结果为啥不一样

[root@oldboy32-vm1 files]#awk -F : -v OFS="$"'{print $0}' reg.txt

ZhangDandan41117397:250:100:175

ZhangXiaoyu390320151:155:90:201

MengFeixue80042789:250:60:50

[root@oldboy32-vm1files]# awk -F : -v OFS="$"'{print $1,$2,$3}' reg.txt

ZhangDandan41117397$250$100

ZhangXiaoyu390320151$155$90

LaoNanhai918391635$250$100

XManX10000$999$999

[root@oldboy32-vm1files]# awk -F : -v OFS="$"'{print $1,$2,$3,$4}' reg.txt

ZhangDandan41117397$250$100$175

ZhangXiaoyu390320151$155$90$201

MengFeixue80042789$250$60$50

[root@oldboy32-vm1files]# awk -F : -v OFS="$"'{$1=$1;print $0}' reg.txt

ZhangDandan41117397$250$100$175

ZhangXiaoyu390320151$155$90$201

LiYoujiu918391635$175$75$300

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

[root@zxwfiles]# awk'BEGIN {FS="[ ]+";OFS=","}{print $2,$1}' reg.txt

Dandan,Zhang

Xiaoyu,Zhang

Feixue,Meng

4.2 正则表达式部分的疑问

[root@demon files]# awk '/^Xiaoyu/' /server/files/reg.txt

[root@demon files]# awk '$2~/^Xiaoyu/' /server/files/reg.txt

/^Xiaoyu/的意思不是以Xiaoyu为开头的字符串吗,为什么默认$0匹配就不行了?

/Xiaoyu/这样就可以了,这是为什么?

解答:

awk不会自动匹配,需要明确告诉它是那一列

^          matches the beginning of astring.  #匹配字符串的开头的位置

$          matches the end of a string.        #匹配字符串结尾的位置

awk '/^Xiaoyu/' /server/files/reg.txt

awk '/Xiaoyu/' /server/files/reg.txt

grep "^Xiaoyu" reg.txt

grep "Xiaoyu" reg.txt

4.3 匹配除了含有oldboy的其他行

4.3.1 测试文件

[root@zxw files]# cat test.txt

lidao

oldboy

oldboylinux

zhangdao

xiadao

[root@zxw files]#

4.3.2 注意精确

[root@oldboy32-vm1files]# awk '/^l|z|x|x$/' test.txt

lidao

oldboylinux

zhangdao

[root@oldboy32-vm1files]# egrep "^l|z|x|x$" test.txt

lidao

oldboylinux

zhangdao

[root@oldboy32-vm1files]# egrep "^l|x$|^z|^x" test.txt

lidao

oldboylinux

zhangdao

4.4 表示一个范围,与sed(2,5p)意思相近

[root@oldboy32-vm1files]# awk 'NR==2,NR==5' awkfile.txt

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

[root@oldboy32-vm1files]# #范围条件/范围模式

4.5 BEGIN在读取文件以前执行

[root@oldboy32-vm1files]# awk 'BEGIN{print 3/10}'

0.3

[root@oldboy32-vm1files]# awk 'BEGIN{print 10/3}'

3.33333

4.6 a=1  输出1 a=lidao  awk会将lidao(英文字母)认为是一个变量(需要加“”)

[root@oldboy32-vm1files]# awk 'BEGIN{a=1;print a}'

1

[root@oldboy32-vm1files]# awk 'BEGIN{a=lidao;print a}'

[root@oldboy32-vm1files]# awk 'BEGIN{a="";print a}'

[root@oldboy32-vm1files]# awk 'BEGIN{a="lidao";print a}'

lidao

4.7 END模式

[root@oldboy32-vm1 files]# awk'BEGIN{print "name","ID"}{print $2,$3}END{print"hello" }' reg.txt

name ID

Dandan 41117397

Xiaoyu 390320151

Feixue 80042789

hello

4.8 awk调试过程

[root@oldboy32-vm1~]# awk '/^$/{notepad++}END{print notepad}'/etc/services16

[root@oldboy32-vm1~]# awk '/^$/{notepad++;print notepad}'/etc/services

1

2

3

4.9 数组

[root@oldboy32-vm1~]# awk'BEGIN{hotel[110]="xiaoyu";hotel[114]="xiadao";

hotel[121]="dandan"

hotel[119]="waiwai"

print hotel[110],hotel[114],hotel[119],hotel[121]}'

xiaoyuxiadao waiwai dandan

[root@oldboy32-vm1~]# awk'BEGIN{hotel[110]="xiaoyu";hotel[114]="xiadao";

hotel[121]="dandan"

hotel[119]="waiwai"

for(pol in hotel )print pol,hotel[pol]}'

110xiaoyu

121dandan

114xiadao

119waiwai

数组

[root@zxw~]# awk 'BEGIN{hotel[100]="zxw";hotel[200]="mzl";hotel[300]="wyf";hotel[400]="yz";for(abc in hotel)print abc,hotel[abc]}'

100 zxw

200 mzl

300 wyf

400 yz

第5章 企业案例

5.1 企业面试题: 按单词出现频率降序排序(计算文件中每个单词的重复数量)

注:(此处使用sort与uniq即可)

[root@oldboy32-vm1files]# #sort 默认是按照字母顺序排列

awk -vRS=" " '{print $0}' count.txt|xargs -n1|sort|uniq -c|sort -nr

awk -vRS=" " '{print $0}' count.txt|sort|uniq -c|sort -nr

5.1.1 按字母查找

awk 'BEGIN{RS="[:0-9/ ]+"}{printNR,$0}' awkfile.txt

awk 'BEGIN{RS="[^a-zA-Z]+"}{printNR,$0}' awkfile.txt

[root@zxwfiles]# awk 'BEGIN{RS=":|/|[0-9]"}{print $0}' awkfile.txt|sort|uniq-c|sort -rn

5.2 考试题1:处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)

oldboy.log

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

5.2.1 答案:

[root@zxwfiles]# awk 'BEGIN{FS="."}{print$3}' oldboy.txt|sort|uniq -c |sort -rn

3 org/index

1 org/3

1 org/2

1 org/1

[root@zxwfiles]#

5.3 【企业面试题】处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)

[root@zxwfiles]# cat oldboy.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@zxwfiles]#

5.3.1 答案:

[root@oldboy32-vm1files]# awk -F "[/.]+" '{h[$2]++;print$2,h["www"]}' url.txt

www 1

www 2

post 2

mp3 2

www 3

post 3

[root@oldboy32-vm1files]# awk -F "[/.]+" '{h[$2]++;print$2,h["www"]}' url.txt

[root@oldboy32-vm1files]# awk -F "[/.]+" '{h[$2]++;print$2,h[""]}' url.txt

[root@oldboy32-vm1files]# awk -F "[/.]+" '{h[$2]++;print$2,h["post"]}' url.txt

[root@oldboy32-vm1files]# awk -F "[/.]+" '{h[$2]++;print$2,h[$2]}' url.txt

[root@oldboy32-vm1files]# awk -F "[/.]+" '{h[$2]++}END{for(polin h) print pol,h[pol]}' url.txt

www 3

mp3 1

post 2

[root@oldboy32-vm1files]# awk -F "[/]+" '{h[$2]++}END{for(polin h) print pol,h[pol]}' url.txt

mp3.etiantian.org1

post.etiantian.org2

www.etiantian.org3

5.3.2 方法一

awk -v RS="[^a-zA-Z]+"'{h[$0]++}END{for(pol in h)print pol,h[pol]}' awkfile.txt |sort-rnk2|column -t

5.3.3 方法二

awk'BEGIN{RS="[^a-zA-Z]+"}{h[$0]++}END{for(pol in h)printpol,h[pol]}' awkfile.txt |sort -rnk2|column -t

 

 

 
posted @ 2017-05-12 10:02  靠岸啊啊  阅读(645)  评论(0编辑  收藏  举报