AWK从入门到精通
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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会把等于看成是一个变量
例子:
[[email protected]~]# 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
记录分隔符 -每一个记录是如何结束的
[[email protected] 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分割符号:
[[email protected]]# head -2 awkfile.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[[email protected]]# 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
[[email protected]]# echo "I am oldboy,my qq is31333741">>/server/files/oldboy.txt
[[email protected]]# cat oldboy.txt
I am oldboy,myqq is 31333741
[[email protected]]# echo oldboy,31333741
oldboy,31333741
[[email protected]]# awk -F " |," ‘{print $3,$NF}‘oldboy.txt
oldboy31333741
[[email protected]]# awk -F " |," ‘{print$3","$NF}‘ oldboy.txt
oldboy,31333741
[[email protected]]# 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
[[email protected]]# cat ors.txt
a
b
c
[[email protected]]# awk ‘BEGIN{ORS="oldboy"}{print $0}‘ors.txt
aoldboyboldboycoldboy[[email protected]]#
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取最后一个区域。
列子
[[email protected]]# ifconfig eth0 |awk ‘NR==2{print $1}‘
inet
[[email protected]]# ifconfig eth0 |awk -F "[ :]+"‘NR==2{print $1}‘
[[email protected]]# ifconfig eth0 |awk -F "[ :]+"‘NR==2{print $2}‘
inet
[[email protected]]# #awk默认的FS 分隔符空格序列一个空格或多个空格 tab 都认为是一样的一个整体
[[email protected]]# #[ \t]+
[[email protected]]# echo -e "\ta\t\tb"
ab
[[email protected]]# echo -e "\ta\t\tb"|awk ‘{print $1}‘
a
[[email protected]]# 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位置
[[email protected]]# 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
[[email protected]]# 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的元字符类似,而且正则表达式是玩转三剑客的必备工具,
以什么开头,精确到列
[[email protected]]# awk ‘$3~/c/‘ count.txt
sync xsync sbin bin sync
uucp xuucp var spool uucp sbin nologin
[[email protected]]# awk ‘$3~/c$/‘ count.txt
sync xsync sbin bin sync
[[email protected]]# awk ‘/c$/‘ count.txt
sync xsync sbin bin sync
[[email protected]]# 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
[[email protected] 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中字母将会被认为是变量,如果真的要给一个变量赋值字母,(字符串),请使用双引号。
[[email protected]]# awk‘BEGIN{abcd=123456;a=abcd;print a}‘
123456
[[email protected]]# awk‘BEGIN{a=abcd;print a}‘
[[email protected]]# 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 测试文件
[[email protected]]# cat reg.txt
ZhangDandan41117397:250:100:175
ZhangXiaoyu390320151:155:90:201
4.1.1 显示姓Zhang的人的第二次捐款金额及她的名字
4.1.1.1 第一种
[[email protected] files]# awk -F "[:]+" ‘/Zhang/{print $1,$2,$6}‘ reg.txt
Zhang Dandan 175
Zhang Xiaoyu 201
4.1.1.2 第二种
[[email protected]]# awk -F "[ :]+" ‘/^Zhang/‘ reg.txt
ZhangDandan41117397:250:100:175
ZhangXiaoyu390320151:155:90:201
4.1.1.3 第三种
[[email protected]]# awk -F "[ :]+" ‘$0~/^Zhang/‘ reg.txt
ZhangDandan41117397:250:100:175
ZhangXiaoyu390320151:155:90:201
4.1.1.4 第四种
[[email protected]]# awk -F "[ :]+" ‘/^Zhang/{print$2,$5}‘ reg.txt
Dandan100
Xiaoyu90
4.1.1.5 注意错误1
[[email protected]]# awk -F "[ :]+" ‘/^Zhang/{print$2,$NF-1}‘ reg.txt
Dandan174
Xiaoyu200
4.1.1.6 注意错误2
[[email protected]]# awk -F "[ :]+" ‘/^Zhang/{print$2,$(NF-1)}‘ reg.txt
Dandan100
Xiaoyu90
4.1.2 显示Xiaoyu的名字和ID号码
[[email protected]]# awk -F "[ :]+" ‘/Xiaoyu/{print$1,$2,$3}‘ reg.txt
ZhangXiaoyu 390320151
4.1.3 显示所有以41开头的ID号码的人的全名和ID号码
[[email protected]]# awk -F "[ :]+" ‘$3~/^41/ {print $1 $2$3}‘ reg.txt
ZhangDandan41117397
LiuBingbing41117483
4.1.4 显示所有以一个D或X开头的人名全名
[[email protected]]# awk -F "[ :]+" ‘$2~/^D|^X/{print$1,$2}‘ reg.txt
ZhangDandan
ZhangXiaoyu
WangXiaoai
4.1.5 显示所有ID号码最后一位数字是1或5的人的全名
[[email protected]]# awk -F "[ :]+" ‘$3~/1$|5$/{print$1,$2}‘ reg.txt
ZhangXiaoyu
WuWaiwai
WangXiaoai
4.1.6 显示Xiaoyu的捐款.每个值时都有以$开头.如$520$200$135
4.1.6.1 第一种
[[email protected]]# awk‘BEGIN {FS=":" ; OFS="$"} {print "$",$2,$3,$4}‘ reg.txt
250$100$175
155$90$201
250$60$50
4.1.6.2 第二种
[[email protected]]# awk ‘$2~/^Xiaoyu$/{print $NF}‘ reg.txt
:155:90:201
[[email protected]]# awk ‘$2~/^Xiaoyu$/{print $NF}‘ reg.txt |tr":" "$"
$155$90$201
[[email protected]]# #sub gsub gensub
[[email protected]]# #gsub
[[email protected]]# #gsub(r, s [, t])
[[email protected]]# #函数
[[email protected]]# #gsub(正则表达式,你要替换成啥[,目标($1 $2 $3)])
[[email protected]]# awk ‘$2~/^Xiaoyu$/{gsub(/:/,"$")}‘reg.txt
[[email protected]]# awk‘$2~/^Xiaoyu$/{gsub(/:/,"$");print $NF}‘ reg.txt
$155$90$201
[[email protected]]# 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)输出的结果为啥不一样
[[email protected] files]#awk -F : -v OFS="$"‘{print $0}‘ reg.txt
ZhangDandan41117397:250:100:175
ZhangXiaoyu390320151:155:90:201
MengFeixue80042789:250:60:50
与
[[email protected]]# awk -F : -v OFS="$"‘{print $1,$2,$3}‘ reg.txt
ZhangDandan41117397$250$100
ZhangXiaoyu390320151$155$90
LaoNanhai918391635$250$100
XManX10000$999$999
[[email protected]]# awk -F : -v OFS="$"‘{print $1,$2,$3,$4}‘ reg.txt
ZhangDandan41117397$250$100$175
ZhangXiaoyu390320151$155$90$201
MengFeixue80042789$250$60$50
[[email protected]]# 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
[[email protected]]# awk‘BEGIN {FS="[ ]+";OFS=","}{print $2,$1}‘ reg.txt
Dandan,Zhang
Xiaoyu,Zhang
Feixue,Meng
4.2 正则表达式部分的疑问
[[email protected] files]# awk ‘/^Xiaoyu/‘ /server/files/reg.txt
[[email protected] 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 测试文件
[[email protected] files]# cat test.txt
lidao
oldboy
oldboylinux
zhangdao
xiadao
[[email protected] files]#
4.3.2 注意精确
[[email protected]]# awk ‘/^l|z|x|x$/‘ test.txt
lidao
oldboylinux
zhangdao
[[email protected]]# egrep "^l|z|x|x$" test.txt
lidao
oldboylinux
zhangdao
[[email protected]]# egrep "^l|x$|^z|^x" test.txt
lidao
oldboylinux
zhangdao
4.4 表示一个范围,与sed(2,5p)意思相近
[[email protected]]# 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
[[email protected]]# #范围条件/范围模式
4.5 BEGIN在读取文件以前执行
[[email protected]]# awk ‘BEGIN{print 3/10}‘
0.3
[[email protected]]# awk ‘BEGIN{print 10/3}‘
3.33333
4.6 a=1 输出1 a=lidao awk会将lidao(英文字母)认为是一个变量(需要加“”)
[[email protected]]# awk ‘BEGIN{a=1;print a}‘
1
[[email protected]]# awk ‘BEGIN{a=lidao;print a}‘
[[email protected]]# awk ‘BEGIN{a="";print a}‘
[[email protected]]# awk ‘BEGIN{a="lidao";print a}‘
lidao
4.7 END模式
[[email protected] 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调试过程
[[email protected]~]# awk ‘/^$/{notepad++}END{print notepad}‘/etc/services16
[[email protected]~]# awk ‘/^$/{notepad++;print notepad}‘/etc/services
1
2
3
4.9 数组
[[email protected]~]# 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
[[email protected]~]# 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
数组
[[email protected]~]# 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即可)
[[email protected]]# #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
[[email protected]]# 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 答案:
[[email protected]]# awk ‘BEGIN{FS="."}{print$3}‘ oldboy.txt|sort|uniq -c |sort -rn
3 org/index
1 org/3
1 org/2
1 org/1
5.3 【企业面试题】处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)
[[email protected]]# 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
5.3.1 答案:
[[email protected]]# awk -F "[/.]+" ‘{h[$2]++;print$2,h["www"]}‘ url.txt
www 1
www 2
post 2
mp3 2
www 3
post 3
[[email protected]]# awk -F "[/.]+" ‘{h[$2]++;print$2,h["www"]}‘ url.txt
[[email protected]]# awk -F "[/.]+" ‘{h[$2]++;print$2,h[""]}‘ url.txt
[[email protected]]# awk -F "[/.]+" ‘{h[$2]++;print$2,h["post"]}‘ url.txt
[[email protected]]# awk -F "[/.]+" ‘{h[$2]++;print$2,h[$2]}‘ url.txt
[[email protected]]# awk -F "[/.]+" ‘{h[$2]++}END{for(polin h) print pol,h[pol]}‘ url.txt
www 3
mp3 1
post 2
[[email protected]]# 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” 博客,转载请与作者联系!
目录
1.5模式及pattern,可以类似理解成sed的模式匹配,可以由表达式组成,也可以是俩个正斜杠之间的正则表达式,比如:NR==1 ,这就是模式,可以理解为一个条件。... 2
1.6动作即action,是由在大括号里面的一条或者多条语句组成,语句之间使用分号隔开,如下awk使用格式... 2
1.8 接下来说俩个新概念:记录和字段,这里为了方便理解可以把记录当做行记录===行,字段相当于列,字段===列。... 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.11.1 NR存放着每个记录的号(行号),读取新行时候会自动加1(+1)... 6
1.11.2 RS是输入数据的记录的分隔符,简单理解就是可以指定每个记录的结尾标致... 6
1.11.4 当我们修改了RS的值,最好配合NR来查看变化,也就是修改了RS的值通过NR查看结果,调试awk程序。... 6
1.16.1 利用OFS调换ETCpasswd位置... 8
1.18 awk也支持大量的正则表达式,大部分与sed的元字符类似,而且正则表达式是玩转三剑客的必备工具,... 9
2.2.1 第二个作用,在读取文件之前输出些提示性信息,表头。... 11
2.6.2 {print NF ,$0} boby 模块处理,处理完毕后... 12
2.6.3 END{print"end of file"} 输出一个结果... 12
4.1.1 显示姓Zhang的人的第二次捐款金额及她的名字... 16
4.1.3 显示所有以41开头的ID号码的人的全名和ID号码... 17
4.1.5 显示所有ID号码最后一位数字是1或5的人的全名... 17
4.1.6 显示Xiaoyu的捐款.每个值时都有以$开头.如$520$200$135. 18
4.4 表示一个范围,与sed(2,5p)意思相近... 21
4.6 a=1输出1a=lidaoawk会将lidao(英文字母)认为是一个变量(需要加“”)... 21
5.1 企业面试题: 按单词出现频率降序排序(计算文件中每个单词的重复数量)... 23
5.2 考试题1:处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)24
5.3 【】企业面试题】处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)24
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会把等于看成是一个变量
例子:
[[email protected]~]# 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
记录分隔符 -每一个记录是如何结束的
[[email protected] 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分割符号:
[[email protected]]# head -2 awkfile.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
[[email protected]]# 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
[[email protected]]# echo "I am oldboy,my qq is31333741">>/server/files/oldboy.txt
[[email protected]]# cat oldboy.txt
I am oldboy,myqq is 31333741
[[email protected]]# echo oldboy,31333741
oldboy,31333741
[[email protected]]# awk -F " |," ‘{print $3,$NF}‘oldboy.txt
oldboy31333741
[[email protected]]# awk -F " |," ‘{print$3","$NF}‘ oldboy.txt
oldboy,31333741
[[email protected]]# 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
[[email protected]]# cat ors.txt
a
b
c
[[email protected]]# awk ‘BEGIN{ORS="oldboy"}{print $0}‘ors.txt
aoldboyboldboycoldboy[[email protected]]#
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取最后一个区域。
列子
[[email protected]]# ifconfig eth0 |awk ‘NR==2{print $1}‘
inet
[[email protected]]# ifconfig eth0 |awk -F "[ :]+"‘NR==2{print $1}‘
[[email protected]]# ifconfig eth0 |awk -F "[ :]+"‘NR==2{print $2}‘
inet
[[email protected]]# #awk默认的FS 分隔符空格序列一个空格或多个空格 tab 都认为是一样的一个整体
[[email protected]]# #[ \t]+
[[email protected]]# echo -e "\ta\t\tb"
ab
[[email protected]]# echo -e "\ta\t\tb"|awk ‘{print $1}‘
a
[[email protected]]# 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位置
[[email protected]]# 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
[[email protected]]# 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的元字符类似,而且正则表达式是玩转三剑客的必备工具,
以什么开头,精确到列
[[email protected]]# awk ‘$3~/c/‘ count.txt
sync xsync sbin bin sync
uucp xuucp var spool uucp sbin nologin
[[email protected]]# awk ‘$3~/c$/‘ count.txt
sync xsync sbin bin sync
[[email protected]]# awk ‘/c$/‘ count.txt
sync xsync sbin bin sync
[[email protected]]# 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
[[email protected] 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中字母将会被认为是变量,如果真的要给一个变量赋值字母,(字符串),请使用双引号。
[[email protected]]# awk‘BEGIN{abcd=123456;a=abcd;print a}‘
123456
[[email protected]]# awk‘BEGIN{a=abcd;print a}‘
[[email protected]]# 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 测试文件
[[email protected]]# cat reg.txt
ZhangDandan41117397:250:100:175
ZhangXiaoyu390320151:155:90:201
4.1.1 显示姓Zhang的人的第二次捐款金额及她的名字
4.1.1.1 第一种
[[email protected] files]# awk -F "[:]+" ‘/Zhang/{print $1,$2,$6}‘ reg.txt
Zhang Dandan 175
Zhang Xiaoyu 201
4.1.1.2 第二种
[[email protected]]# awk -F "[ :]+" ‘/^Zhang/‘ reg.txt
ZhangDandan41117397:250:100:175
ZhangXiaoyu390320151:155:90:201
4.1.1.3 第三种
[[email protected]]# awk -F "[ :]+" ‘$0~/^Zhang/‘ reg.txt
ZhangDandan41117397:250:100:175
ZhangXiaoyu390320151:155:90:201
4.1.1.4 第四种
[[email protected]]# awk -F "[ :]+" ‘/^Zhang/{print$2,$5}‘ reg.txt
Dandan100
Xiaoyu90
4.1.1.5 注意错误1
[[email protected]]# awk -F "[ :]+" ‘/^Zhang/{print$2,$NF-1}‘ reg.txt
Dandan174
Xiaoyu200
4.1.1.6 注意错误2
[[email protected]]# awk -F "[ :]+" ‘/^Zhang/{print$2,$(NF-1)}‘ reg.txt
Dandan100
Xiaoyu90
4.1.2 显示Xiaoyu的名字和ID号码
[[email protected]]# awk -F "[ :]+" ‘/Xiaoyu/{print$1,$2,$3}‘ reg.txt
ZhangXiaoyu 390320151
4.1.3 显示所有以41开头的ID号码的人的全名和ID号码
[[email protected]]# awk -F "[ :]+" ‘$3~/^41/ {print $1 $2$3}‘ reg.txt
ZhangDandan41117397
LiuBingbing41117483
4.1.4 显示所有以一个D或X开头的人名全名
[[email protected]]# awk -F "[ :]+" ‘$2~/^D|^X/{print$1,$2}‘ reg.txt
ZhangDandan
ZhangXiaoyu
WangXiaoai
4.1.5 显示所有ID号码最后一位数字是1或5的人的全名
[[email protected]]# awk -F "[ :]+" ‘$3~/1$|5$/{print$1,$2}‘ reg.txt
ZhangXiaoyu
WuWaiwai
WangXiaoai
4.1.6 显示Xiaoyu的捐款.每个值时都有以$开头.如$520$200$135
4.1.6.1 第一种
[[email protected]]# awk‘BEGIN {FS=":" ; OFS="$"} {print "$",$2,$3,$4}‘ reg.txt
250$100$175
155$90$201
250$60$50
4.1.6.2 第二种
[[email protected]]# awk ‘$2~/^Xiaoyu$/{print $NF}‘ reg.txt
:155:90:201
[[email protected]]# awk ‘$2~/^Xiaoyu$/{print $NF}‘ reg.txt |tr":" "$"
$155$90$201
[[email protected]]# #sub gsub gensub
[[email protected]]# #gsub
[[email protected]]# #gsub(r, s [, t])
[[email protected]]# #函数
[[email protected]]# #gsub(正则表达式,你要替换成啥[,目标($1 $2 $3)])
[[email protected]]# awk ‘$2~/^Xiaoyu$/{gsub(/:/,"$")}‘reg.txt
[[email protected]]# awk‘$2~/^Xiaoyu$/{gsub(/:/,"$");print $NF}‘ reg.txt
$155$90$201
[[email protected]]# 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)输出的结果为啥不一样
[[email protected] files]#awk -F : -v OFS="$"‘{print $0}‘ reg.txt
ZhangDandan41117397:250:100:175
ZhangXiaoyu390320151:155:90:201
MengFeixue80042789:250:60:50
与
[[email protected]]# awk -F : -v OFS="$"‘{print $1,$2,$3}‘ reg.txt
ZhangDandan41117397$250$100
ZhangXiaoyu390320151$155$90
LaoNanhai918391635$250$100
XManX10000$999$999
[[email protected]]# awk -F : -v OFS="$"‘{print $1,$2,$3,$4}‘ reg.txt
ZhangDandan41117397$250$100$175
ZhangXiaoyu390320151$155$90$201
MengFeixue80042789$250$60$50
[[email protected]]# 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
[[email protected]]# awk‘BEGIN {FS="[ ]+";OFS=","}{print $2,$1}‘ reg.txt
Dandan,Zhang
Xiaoyu,Zhang
Feixue,Meng
4.2 正则表达式部分的疑问
[[email protected] files]# awk ‘/^Xiaoyu/‘ /server/files/reg.txt
[[email protected] 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 测试文件
[[email protected] files]# cat test.txt
lidao
oldboy
oldboylinux
zhangdao
xiadao
[[email protected] files]#
4.3.2 注意精确
[[email protected]]# awk ‘/^l|z|x|x$/‘ test.txt
lidao
oldboylinux
zhangdao
[[email protected]]# egrep "^l|z|x|x$" test.txt
lidao
oldboylinux
zhangdao
[[email protected]]# egrep "^l|x$|^z|^x" test.txt
lidao
oldboylinux
zhangdao
4.4 表示一个范围,与sed(2,5p)意思相近
[[email protected]]# 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
[[email protected]]# #范围条件/范围模式
4.5 BEGIN在读取文件以前执行
[[email protected]]# awk ‘BEGIN{print 3/10}‘
0.3
[[email protected]]# awk ‘BEGIN{print 10/3}‘
3.33333
4.6 a=1 输出1 a=lidao awk会将lidao(英文字母)认为是一个变量(需要加“”)
[[email protected]]# awk ‘BEGIN{a=1;print a}‘
1
[[email protected]]# awk ‘BEGIN{a=lidao;print a}‘
[[email protected]]# awk ‘BEGIN{a="";print a}‘
[[email protected]]# awk ‘BEGIN{a="lidao";print a}‘
lidao
4.7 END模式
[[email protected] 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调试过程
[[email protected]~]# awk ‘/^$/{notepad++}END{print notepad}‘/etc/services16
[[email protected]~]# awk ‘/^$/{notepad++;print notepad}‘/etc/services
1
2
3
4.9 数组
[[email protected]~]# 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
[[email protected]~]# 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
数组
[[email protected]~]# 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即可)
[[email protected]]# #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
[[email protected]]# 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 答案:
[[email protected]]# awk ‘BEGIN{FS="."}{print$3}‘ oldboy.txt|sort|uniq -c |sort -rn
3 org/index
1 org/3
1 org/2
1 org/1
5.3 【企业面试题】处理以下文件内容,将域名取出并根据域名进行计数排序处理:(百度和sohu面试题)
[[email protected]]# 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
5.3.1 答案:
[[email protected]]# awk -F "[/.]+" ‘{h[$2]++;print$2,h["www"]}‘ url.txt
www 1
www 2
post 2
mp3 2
www 3
post 3
[[email protected]]# awk -F "[/.]+" ‘{h[$2]++;print$2,h["www"]}‘ url.txt
[[email protected]]# awk -F "[/.]+" ‘{h[$2]++;print$2,h[""]}‘ url.txt
[[email protected]]# awk -F "[/.]+" ‘{h[$2]++;print$2,h["post"]}‘ url.txt
[[email protected]]# awk -F "[/.]+" ‘{h[$2]++;print$2,h[$2]}‘ url.txt
[[email protected]]# awk -F "[/.]+" ‘{h[$2]++}END{for(polin h) print pol,h[pol]}‘ url.txt
www 3
mp3 1
post 2
[[email protected]]# 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
以上是关于AWK从入门到精通的主要内容,如果未能解决你的问题,请参考以下文章