【shell】shell脚本实战-awk工作模式讲解

举报
互联网老辛 发表于 2021/06/09 00:33:24 2021/06/09
【摘要】 文章目录 awk工作的三个步骤awk中的各种模式详解1. awk 脚本拥有的形式2. 正则表达式3. 关系表达式4. 组合的Pattern(模式)5. Pattern1,Pattern26. BEGINa) 给文件开头添加信息b) 取eth0的ip地址 7. END1) 给文件结尾 添加信息2) 统计 /etc/services 文件中的空行的数量 3) 显示用...

awk工作的三个步骤

  • 读:从文件、管道或标准输入中读入一行然后把它存放到内存中
  • 执行:对每一行数据,根据AWK命令按顺序执行。默认情况是处理每一行数据,也可以指定模式
  • 重复:一直重复上述两个过程直到文件结束

awk中的各种模式详解

1. awk 脚本拥有的形式
awk  '/pattern/ { actions }' filename

  
 
  • 1

你通常会发现脚本中的模式(/pattern/)是一个正则表达式,此外,你也可以在这里用特殊模式 BEGIN 和 END。因此,我们也能按照下面的形式编写一条 awk 命令:

awk 'BEGIN { actions } /pattern/ { actions } /pattern/ { actions }...END { actions }' filenames

  
 
  • 1

语法结构如下图:
在这里插入图片描述
其中:BEGIN END是AWK的关键字部,因此必须大写;这两个部分开始块和结束块是可选的

特殊模块:
BEGIN语句设置计数和打印头部信息,在任何动作之前进行
END 语句输出统计结果,在完成动作之后执行

awk通过Pattern(模式)来控制是否处理当前记录,如果当前记录和Pattern匹配,则执行Action(操作)。在awk中,有下列几种模式:

1、正则表达式
2、关系表达式
3、组合的Pattern
4、Pattern1,Pattern2
5、BEGIN
6、END

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

为了说明以上各种模式,我们这里准备一个文件score.txt,以实例的方式一一进行说明,score.txt文件内容如下:

[root@ecs-c13b awk]# cat score.txt 
guojing 85 92 78
zhaoyun 89 90 75
sanfeng 84 88 80
guanyu 83 78 90
liubei 86 88 79

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
2. 正则表达式
  • 查询有一门课程成绩在90-99区间的学习的成绩。
[root@ecs-c13b awk]# awk '/9[0-9]/ {print $0}' score.txt 
guojing 85 92 78
zhaoyun 89 90 75
guanyu 83 78 90


  
 
  • 1
  • 2
  • 3
  • 4
  • 5

以上指令查询有一门课成绩在[90-99]区间的学生的成绩信息,/9[0-9]/部分即为awk程序指令中的Pattern,这里Pattern的类型为正则表达式。

awk '$3 ~ /9[0-9]/ {print $0}' score.txt

zhaosan 85 92 78
lisheng 89 90 75

  
 
  • 1
  • 2
  • 3
  • 4

这条指令在上一条指令的基础上增加了限制,需要第二门课(数学)成绩在[90-99]区间才可与模式匹配。这里的 ~ 操作符用来表示变量是否与正则表达式匹配,如果要判断不匹配,可以使用 !~ 操作符。

3. 关系表达式
awk '$3 >= 90 {print $0}' score.txt

zhaosan 85 92 78
lisheng 89 90 75

  
 
  • 1
  • 2
  • 3
  • 4

可用来形成模式关系运算符包括: <(小于)、>(大于)、<=(小于或等于)、>=(大于或等于)、= =(等于)和 ! =(不等于)。

这条指令的作用也是查询数学成绩在90分以上的学生成绩信息,不过比正则表达式中的范围要大一点,这里100分也是符合模式的。

4. 组合的Pattern(模式)
awk '$3 >= 90 && $3 < 100 {print $0}' score.txt

zhaosan 85 92 78
lisheng 89 90 75

  
 
  • 1
  • 2
  • 3
  • 4

布尔运算符 ||(或)&&(和)以及 !(不)将模式组合,组合后如果求值为真则模式匹配,否则不匹配。这里就解决了关系表达式示例中包含了100的问题。

5. Pattern1,Pattern2
awk 'FNR == 2 , FNR == 4 {print $0}' score.txt

lisheng 89 90 75
zhaoyun 84 88 80
guanyu 83 78 90

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

其实这个也可以归为组合的模式中,只是这种模式比较特殊,故单独列出。以,(逗号)隔开的两个Pattern指定一个范围,对从匹配第一个Pattern的记录开始,到匹配第二个Pattern结束的所有记录执行Action

6. BEGIN

BEGIN模块在awk读取文件之前就执行,一般用来定义我们的内置变量(预定义变量,eg:FS,RS)可以输出表头(excel表格名称)

BEGIN模式之前在实例中提到,自定义变量,给内容变量赋值等,都是使用过。需要注意的是BEGIN模式后面要结合一个action操作块,包含在大括号内

awk必须在对输入文件进行任何处理前先执行BEGIN定义的action操作块。我们可以不要任何输入文件,就可以对BEGIN模块进行测试,因为awk需要先执行完BEGIN模式,才对输入文件做处理。BEGIN模式常常被用来修改内置变量ORS,RS,FS,OFS,等的值。

a) 给文件开头添加信息

假如我们要将学生成绩表打印出来,那总得加点表头什么的吧,就可以放到BEGIN中了。

awk 'BEGIN { print "Print student score table"} {print $0}' score.txt

Print student score table
zhaosan 85 92 78
lisheng 89 90 75
zhaoyun 84 88 80
guanyu 83 78 90
liubei 86 88 79

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
b) 取eth0的ip地址
ifconfig eth0|awk -F '(addr:)|(Bcast:)' 'NR==2{print $2}'
ifconfig eth0|awk -F '[: ]+' 'NR==2{print $4}'
ifconfig eth0|awk -F '[^0-9.]+' 'NR==2{print $2}'

  
 
  • 1
  • 2
  • 3

也可以写成

ifconfig eth0|awk  'BEGIN{FS="(addr:)|(Bcast:)"} NR==2{print $2}'
ifconfig eth0|awk  'BEGIN{FS="[^0-9.]+"} NR==2{print $2}'
ifconfig eth0|awk  'BEGIN{FS="[: ]+"} NR==2{print $4}'

  
 
  • 1
  • 2
  • 3

注意:命令行 -F 本质就是修改FS的变量。

7. END

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

1) 给文件结尾 添加信息
awk 'END { print "Work done"} {print $0}' score.txt

zhaosan 85 92 78
lisheng 89 90 75
zhaoyun 84 88 80
guanyu 83 78 90
liubei 86 88 79
Work done

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
2) 统计 /etc/services 文件中的空行的数量

统计数量: grep -c 或 awk

[root@mysql-master ~]# awk '/^$/{print $0}' /etc/services |wc -l
16

[root@mysql-master ~]# grep -c '^$' /etc/services
16

[root@mysql-master ~]# awk '/^$/{i++}END{print i}' /etc/services
16
[root@mysql-master ~]# awk '/^$/{i=i+1}END{print i}' /etc/services
16

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
3) 显示用户信息配置文件中uid大于500的用户名及uid信息并在开头显示“用户名 UID”字样,在结尾显示“the over"
awk -F: 'BEGIN { print "用户名 UID"} END { print "the over"} $3>500{print $1,$3}' /etc/passwd

  
 
  • 1

补充:awk中变量使用

直接定义,直接使用即可。

awk中字母会被认为是变量,如果真的要给一个变量赋值使用双引号

[root@mysql-master ~]# awk 'BEGIN{ a=123asdf;print a}' #awk中字母会被认为是变量
123
[root@mysql-master ~]# awk 'BEGIN{ a="123asdf";print a}' #awk中给变量赋值要加双引号;使用变量直接使用即可
123asdf

  
 
  • 1
  • 2
  • 3
  • 4

文章来源: zmedu.blog.csdn.net,作者:互联网老辛,版权归原作者所有,如需转载,请联系作者。

原文链接:zmedu.blog.csdn.net/article/details/108098226

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。