概念
-
awk是Linux以及UNIX环境中现有的功能最强大的数据处理工具,awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母
-
awk是一种处理文本数据的编程语言,适合文本处理和报表生成,awk的设计使得它非常适合于处理由行和列组成的文本数据。
-
awk 还是一种编程语言环境,它提供了正则表达式的匹配,流程控制,运算符,表达式,变量以及函数等一系列的程序设计语言所具备的特性,它从C语言中获取了一些优秀的思想
工作流程
如图:
流程:
-
第一步:自动从指定的数据文件中读取行文本。
-
第二步:自动更新awk的内置系统变量的值,例如列数变量NF、行数变量NR、行变量$0以及各个列变量$1、$2等等
-
第三步:依次执行程序中所有的匹配模式及其操作
-
第四步:当执行完程序中所有的匹配模式及其操作之后,如果数据文件中仍然还有为读取的数据行,则返回到第(1)步,重复执行(1)~(4)的操作。
awk命令的基本语法
-
任何awk语句都由模式(
pattern
)和动作(action
)组成-
模式:由一组用于测试输入行是否需要执行动作的==规则==
-
动作:包含语句,函数和表达式的执行过程
-
简言之,模式决定动作何时触发和触发事件,动作执行对输入行的处理
-
格式:
awk 'BEGIN{ commands } pattern{ commands } END{ commands }' [INPUTFILE…]
# 以上三部分可选
BEGIN模式与END模式
-
BEGIN模式是一种特殊的内置模式,其执行的时机为awk程序刚开始执行,但是又尚未读取任何数据之前。因此,该模式所对应的操作仅仅被执行一次,当awk读取数据之后,BEGIN模式便不再成立。所以,用户可以将与数据文件无关,而且在整个程序的生命周期中,只需执行1次的代码放在BEGIN模式对应的操作中,一般用于打印报告的标题和更改内在变量的值
-
END模式是awk的另外一种特殊模式,该模式执行的时机与BEGIN模式恰好相反,它是在awk命令处理完所有的数据,即将退出程序时成立,在此之前,END模式并不成立。无论数据文件中包含多少行数据,在整个程序的生命周期中,该模式所对应的操作只被执行1次。因此,一般情况下,用户可以将许多善后工作放在END模式对应的操作中EN,一般用于打印总结性的描述或数值总和
-
例
[root@server ~]# awk 'BEGIN {print "BEGIN..."} {print $0} END {print "The End"}' /etc/fstab
[root@server ~]# awk 'BEGIN {print "line one \n line two \n line three"}'
[root@server ~]# awk 'BEGIN {print "this is test"}'
awk的输出
格式:
awk 'BEGIN{ commands } {print item1,item2,……} END{ commands }' [INPUTFILE…]
-
各项目之间使用逗号隔开,而输出时则以空格字符分隔
-
输出的item可以为字符串或数值、当前记录的字段(如$1)、变量或awk的表达式;数值会先转换为字符串,然后再输出
awk程序执行方式
通过命令行执行awk程序
[root@server ~]# vim input
# 输入多个回车符
[root@server ~]# awk '/^$/{print "This is a blank line"}' input
awk命令调用脚本执行
-
在awk程序语句比较多的情况下,用户可以将所有的语句写在一个脚本文件中,然后通过awk命令来解释并执行其中的语句。awk调用脚本的语法如下
awk -f program-file file
-
-f选项表示从脚本文件中读取awk程序语句,program-file表示awk脚本文件名称,file表示要处理的数据文件
-
例
[root@server ~]# vim scr.awk # 新建awk脚本,输入以下内容
/^$/{print "This is a blank line"}
[root@server ~]# awk -f scr.awk input
直接使用awk脚本文件调用
-
在上面介绍的两种方式中,用户都需要输入awk命令才能执行程序。除此之外,用户还可以通过类似于Shell脚本的方式来执行awk程序。在这种方式中,需要在awk程序中指定命令解释器,并且赋予脚本文件的可执行权限。其中指定命令解释器的语法如下
#!/bin/awk -f
以上语句必须位于脚本文件的第一行
通过以下命令执行awk程序:
./awk-script.awk file
例:
[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 input
记录和域
概念
-
awk认为输入文件是结构化的,awk将每个输入文件行定义为记录,行中的每个字符串定义为域,域之间用空格,Tab键或其他符号进行分隔,分隔域的符号就叫做分隔符,默认为空格或tab
-
awk定义域操作符
$
来指定执行动作的域,域操作符$
后面跟数字或变量来标识域的位置,每条记录的域从1开始编号,如$1
表示第一个域$0
表示所有域
例
# 准备示例文件
[root@server ~]# vim awk1.txt
# 输入以下内容
Li xiaoming xian 13311111111
zhang cuihua baoji 13322222222
wang xiaoer xianyang 13333333333
[root@server ~]# vim awk1.txt
[root@server ~]# awk '{print $0}' awk1.txt # 所有域
Li xiaoming xian 13311111111
zhang cuihua baoji 13322222222
wang xiaoer xianyang 13333333333
[root@server ~]# awk '{print $1}' awk1.txt # 第一个域,即第一列
Li
zhang
wang
[root@server ~]# awk '{print $2}' awk1.txt
xiaoming
cuihua
xiaoer
[root@server ~]# awk '{print $3}' awk1.txt
xian
baoji
xianyang
[root@server ~]# awk '{print $4}' awk1.txt # 第4例
13311111111
13322222222
13333333333
# 操作符$之后可以跟变量或表达式
[root@server ~]# awk 'BEGIN {one=1;two=2} {print $(one+two)}' awk1.txt
xian
baoji
xianyang
[root@server ~]# awk '/^[^#]/{print $3}' /etc/fstab
xfs
xfs
swap
# ^[^#]表示不以#开头的行
#检索包含swap的第一列信息
[root@server ~]# awk '/swap/{print $1}' /etc/fstab
使用-F 参数指定域的间隔符
# 查询文件中的所有账户名
[root@server ~]# awk -F ":" '{print $1}' /etc/passwd # 指定冒号为分隔符
#查询文件中的UID与GID
[root@server ~]# awk -F ":" '{print $3,$4}' /etc/passwd
通过系统变量FS改变分隔符
awk默认的分隔符存储在FS变量中,默认为空格或tab
[root@server ~]# awk 'BEGIN {print $FS}'
设置FS变量改变域分隔符
[root@server ~]# awk 'BEGIN {FS=":"} {print $2}' /etc/passwd
NR、NF、FILENAME量
-
概念:
-
NR变量表示记录数,即被处理过的行数
-
NF变量表示记录的域数量
-
FILENAME:处理的文件名
-
-
示例
[root@server ~]# awk '{print NF,NR,$0} END {print FILENAME}' awk1.txt
4 1 Li xiaoming xian 13311111111
4 2 zhang cuihua baoji 13322222222
4 3 wang xiaoer xianyang 13333333333
awk1.txt
[root@server ~]# awk '{print "第",NR,"行","有",NF,"域" > "/root/t1.txt"}' awk1.txt
[root@server ~]# cat t1.txt
第 1 行 有 4 域
第 2 行 有 4 域
第 3 行 有 4 域
awk的变量
概念
-
与其他的程序设计语言一样,awk本身支持变量的相关操作,包括变量的定义和引用,以及参与相关的运算等。此外,还包含了许多内置的系统变量
-
变量的作用是用来存储数据。变量由变量名和值两部分组成,其中变量名是用来实现变量值的引用的途径,而变量值则是内存空间中存储的用户数据
-
awk的变量名只能包括字母、数字和下划线,并且不能以数字开头。例如abc、a、z以及a123都是合法的变量名,而123abc则是非法的变量名。另外,awk的变量名是区分大小写的,因此,X和x分别表示不同的变量
-
awk中的变量类型分为两种,分别为字符串和数值。但是在定义awk变量时,毋需指定变量类型,awk会根据变量所处的环境自动判断。==如果没有指定值,数值类型的变量的缺省值为0,字符串类型的变量的缺省值为空串==
内置变量
变量 | 作用 |
---|---|
$0 | 记录变量,表示所有列的内容 |
$n | 字段变量,表示第n个列的内容 |
NF | 当前行的列个数 |
NR | 显示每一行的行号 |
FS | 输入字段分隔符,默认值是空格或者制表符,可使用-F指定分隔符 |
OFS | 输出字段分隔符 ,OFS=”#”指定输出分割符为# |
RS | 记录分隔符,默认值是换行符 \n |
ENVIRON | 当前shell环境变量及其值的关联数组 |
示例
# 准备数据文件
[root@server ~]# vim awk2.txt # 输入以下内容
zhangsan 68 88 92 45 71
lisi 77 99 63 52 84
wangwu 61 80 93 77 81
[root@server ~]# vim test.awk
{
print
print "$0:",$0
print "$1:",$1
print "$2:",$2
print "NF:",NF
print "NR:",NR
print "FILENAME:",FILENAME
}
# awk命令调用脚本
[root@server ~]# awk -f test.awk awk2.txt
# OFS设置输出结果的间隔符为\t
[root@server ~]# awk -F ":" 'BEGIN {OFS="\t"} {print $1,$2}' /etc/passwd
# 京东面试题:查看文件中所有空白行的行号
[root@server ~]# awk '/^$/{print NR}' /root/anaconda-ks.cfg