RHCE---shell脚本编程之awk


前言

前文已详细了介绍了文本三剑客的其中两种grep 和 sed 命令,本文将介绍文本三剑客中的最后一种awk。


 一.awk概念

    AWK是一种用于文本处理和数据提取的工具。 它可以在命令行中使用,也可以作为脚本运行。 AWK通过处理文本流行来实现数据提取、格式化输出等功能  。

    awk 还是一种编程语言环境,它提供了正则表达式的匹 配,流程控制,运算符,表达式,变量以及函数等一系列 的程序设计语言所具备的特性,它从C语言中获取了一些 优秀的思想

 二.工作流程

  •  第一步:自动从指定的数据文件中读取行文本。
  • 第二步:自动更新awk的内置系统变量的值,例如列数变 量NF、行数变量NR、行变量 以及各个列变量1、$2等等
  • 第三步:依次执行程序中所有的匹配模式及其操作
  • 第四步:当执行完程序中所有的匹配模式及其操作之后, 如果数据文件中仍然还有为读取的数据行,则返回到第 (1)步,重复执行(1)~(4)的操作

 三.awk执行方式

任何awk语句都由模式( pattern )和动作( action )组成

  • 模式:由一组用于测试输入行是否需要执行动作的规则
  • 动作:包含语句,函数和表达式的执行过程
  • 简言之,模式决定动作何时触发事件,动作决定执行的处理动作

 四.awk 语法结构及案例

 语法结构

纯命令执行脚本 

awk 'pattern {action}' file#代表需要被执行的文件
#pattern是正文模式,用于筛选输入数据的行
#上述pattern是三种模式中的一种,剩余两种模式分别是begin和end模式
#action是执行动作,用于对符合特定条件的行执行某些操作
  •  begin模式:处理正文之前的准备工作都在此模式下执行
  • end模式:正文处理结束退出之前的工作都在此模式下执行,简称收尾模式
  • 例如:awk命令是执行依次正文内容输出一个结果,想要将正文全部处理结束之后一次性输出处理结果,则需要将输出工作放到end模式下

格式: 

awk 'BEGIN{ commands } {print item1,item2,……} END{ commands }' [INPUTFILE…]
#begin 模式 命令用逗号隔开 输出以空格输出

参数: 

  1. -F:指定分隔符
  2. -v:定义变量
  3. -f:从文件中读取awk脚本
  4. -F: '{print $2}':指定脚本
  5. -NR:输出指定范围的行
  6. -NF:输出当前行的字段数
  7. -OFS:指定输出分隔符
  8. -ORS:指定输出行分隔符
  9. -i:直接修改文件

 案列 1:

[root@timeserver ~]# vim input
#输入多个回车制造多个空白行

[root@timeserver ~]#  awk '/^$/{print   "This is a blank line"}' input
This is a blank line
This is a blank line
This is a blank line
This is a blank line
#脚本调用流程为:模式条件/^$/检索空白行,匹配到一个空白行执行一个动作:print   "This is a blank line

 案例 2:

[root@server ~]# awk 'BEGIN{print "BEGIN ...."} {print $0}   END{print "The End"}' /etc/fstab
# $0 代表这一行的所有列

上述命令执行流程: 

#首先执行begin 模式打印一个抬头信息 ....
#接着执行pattern模式处理正文(print $0),读取正文第一行的所有列然后输出,
#第一行处理结束输出之后继续处理第二行输出,awk是按行顺序进行处理的
#最后执行end模式,进行最后的收尾工作

 awk命令调用脚本执行

  •  推荐模式和动作有多个时使用此方式执行
[root@server ~]# vim scr.awk
#编辑以下内容
/^$/{print   "This is a blank line"}
#使用awk命令调用脚本执行
[root@server ~]# awk -f scr.awk input
This is a blank line
This is a blank line
This is a blank line

 直接awk纯脚本执行

[root@server ~]# vim scr.awk
#首先编辑抬头申明脚本解释器
#!/bin/awk -f
/^$/{print   "This is a blank line"}
#使用如下命令执行脚本
[root@server ~]chmod o+x scr.awk
[root@server ~]./scr.awk   inout#被处理的文件名

五.记录和域

 概念:

 域:在awk中,域(field)是一行文本中的一个单独的数据项,通常由空格或制表符分隔。默认情况下,awk将输入行按照空格或制表符来划分域,默认为空格或tab

 记录:记录(record)是指awk处理的一行完整的输入文本。默认情况下,记录是以换行符为分隔符来定义的。在awk中,每个记录可以包含多个域,每个域可以通过域分隔符来分隔。$1表示第一个域 $0表示所有域 。

简尔言之:记录代表行,域代表列

 案例1:处理每一行每一列

[root@timeserver ~]# awk '{print $0}' awk1.txt
#截取第一列为$1 第二列为$2

 案例2:$之后的域使用变量定义

[root@server ~]# awk 'BEGIN{one=1 ; two=2} {print $(one+two)}' awk1.txt 

 案例3:查询包含 l 的行显示第三列

[root@server ~]# awk '/^l/{print $3}' awk1.txt

案列4: 输出所有账户

[root@server ~]# awk -F ":" '{print $1}' /etc/passwd
  •  awk默认识别空格来识别列与列,特殊文件中没有空格及awk默认识别的分隔符
  • 需要使用参数 -F 来指定分割符

 六.awk的变量

$0: 记录变量表示所有域(列) $n 字段变量,表示第n个域(列)

NF: 当前记录的域个数

NR :显示每一行的行号

FS: 输入字段分隔符,默认值是空格或者制表 符,可使用-F指定分隔符

OFS: 输出字段分隔符 ,OFS=”#”指定输出分割符 为# RS 记录分隔符,默认值是换行符 \n ENVIRON:当前shell环境变量及其值的关联数组

FILENAME:被awk处理的文件名

案列1:输出所有账户

[root@server ~]# awk 'BEGIN{FS=":"} {print $1}' /etc/passwd
#在begin 模式下设置分隔符

 案列2:使用 NR NF显示行数 列数

[root@server ~]# awk '{print NF,NR,$0} END{print FILENAME}' awk1.txt 
#FILENAME 代表处理的文件名

[root@server ~]# awk '{print "第",NR,"行","有",NF,"列"}' > "/root/t1.txt" awk1.txt

 

 案例 3:

[root@server ~]# awk -F ":" 'BEGIN{OFS="\t"} {print   $1,$3}' /etc/passwd

 案例4:

[root@server ~]# vim awk2.txt
zhangsan  68 88 92 45 71
lisi      77 69 43 52 84
wangwu    61 99 85 77 56


[root@server ~]# vim test.awk
{
       print
       print  "$0:" , $0
       print  "$1:" , $1
       print  "$2:" , $2
       print  "NF:" , NF
       print  "NR:" , NR
       print  "FILENAME: " , FILENAME
}       

[root@server ~]# awk -f test.awk  awk2.txt
#执行过程如下
#awk按行处理,执行第一条命令

 处理结果如下

zhangsan  68 88 92 45 71
$0: zhangsan  68 88 92 45 71
$1: zhangsan
$2: 68
NF: 6
NR: 1
FILENAME: awk2.txt
lisi      77 69 43 52 84
$0: lisi      77 69 43 52 84
$1: lisi
$2: 77
NF: 6
NR: 2
FILENAME: awk2.txt
wangwu    61 99 85 77 56
$0: wangwu    61 99 85 77 56
$1: wangwu
$2: 61
NF: 6
NR: 3
FILENAME: awk2.txt

 面试题:查看文件中空白行的行号

[root@server ~]# awk '/^$/{print NR}' /etc/sos/sos.conf 
#先使用awk筛选文件中的空白行,再使用awk对筛选出的内容进行指定操作

 七.awk中的操作符

算数运算符:

  算术运算符:+、-、*、/、%  ^(指数) **(指数)(分别表示加、减、乘、除和取模 )

案例1: 使用算数运算符进行计算

[root@server ~]# awk 'BEGIN {x=2;y=3;print x+y , x-y , x/y , x%y , x^y , x**y}'

 案例2:统计某个目录文件中占用的字节数

[root@server ~]# ll /etc | awk 'BEGIN{size=0} {size=size+$5} END{print "size is :", size/1024 , "KB"} '
#$5:第五列
#BEGIN中的内容在处理正文前执行,处理正文过程中不执行
#END中的内容在处理正文完毕后最后执行
#上述命令处理过程:
#使用 ll 查询文件内容使用管道符 | 将查询内容交给awk命令处理
#awk命令中BEGIN定义开头输出内容:将0赋值给size 正文处理过程中将第五列的值从第一行开始累加
#最后使用END机构一次性输出结果,若不使用END,则按照awk规则,处理一行文本即输出一次处理结果

赋值运算符 :

赋值运算符:=   +=  -= /= %= ^=

 -= :是一个简写形式的赋值运算符,表示减去某个数并将其结果赋值给一个变量

[root@server ~]# awk 'BEGIN{a=5 ; print a+=5 , a-=5 , a/=5 }'
#上述命令处理过程:awk按行处理,每处理一行输出一个结果,先将5赋值给a,再将a=5时+5之后的值赋值给a,#此时a=10接着再将a的值-5之后赋值给a,最后将a的值/5之后赋值给a,最后输出结果

 条件运算符:

格式: 条件表达式?表达式1:表达式2

注意:?: 类似于 条件语句 if else 

案例: 输出最大值

[root@server ~]# vim awk3.txt
3 6
10 9
3 3
7 5
[root@server ~]# awk '{max=$1>$2?$1:$2 ; print NR , "max=", max }' awk3.txt 

逻辑运算符: 

 &&   || !(取反)

关系运算符 

 > (大于)  <   >=   =   ==   !=   ~(匹配)   !~(不匹 配)

案例:显示本地IP地址

[root@server ~]# ifconfig ens160 | awk 'NR==2{print $2}'  

 案例:查询/etc/passwd 文件第三列小于10以下的行,仅输 出账户和UID

[root@server ~]# awk 'BEGIN{FS=":"} $3<10{print $1,$3}' /etc/passwd

其它运算符 

 ++  --   +  -

 案例:

[root@server ~]# awk 'BEGIN{a=3 ; print a++,++a}'
#a++:置后自增:先输出a之后数值+1
#++a:置前自增:先数值+1再输出a

案例2:awk中操作数为字符串时参与算术运算会被转为数值0  

[root@server ~]# awk 'BEGIN{a="china" ; print a++,++a}'
#将字符串赋值给a,a参与算数运算时将自动转化为数值0

 


总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北 染 星 辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值