awk 是一门语言,这当之无愧!awk 除了简单的文本处理功能,awk具有计算机语言所特有的性质,例如变量、判断、循环、甚至数组。
简单的功能:
awk 处理文本时,将文本分成一条一条的记录,awk允许通过匹配代码(正则)匹配记录;每条记录都包含多个字段,awk可以修改字段分隔符来灵活的隔开字段。它提供了($0,$1...)访问各个字段。
awk 常被用于处理字段。所谓字段,就是文本文件中,每一行分成许多列,列与列之间用特定的字符隔开。
awk 命令分三部分: awk 本身 、 awk要执行的命令内容 、awk的输入文件。
awk 执行命令时,依次读取每一行,将命令应用到每一行。
- print 和 print $0 行为完全相同,都是打印一整行!
-F 参数设置的是awk的初始化变量FS,
FS控制着awk的字段分隔符,默认情况下是空白字符。
awk 支持设置多个字段分隔符,甚至用正则表达式来设置。
eg. awk -F"[\t ]+" // 表示此分隔符匹配一个或多个制表符或空格符
awk读取标准输入。
AWK的代码结构:
awk默认对每一个输入行执行一段代码块。
awk的运行可看成3部分:处理输入前的初始化(BEGIN{}代码块)、处理输入过程({}代码块集合)、处理完所有输入后的扫尾工作(END{}代码块)。
BEGIN代码块,主要完成awk部分参数的初始化操作!
核心
处理输入的过程:执行体
END代码块,是在所有输入都处理完成后awk才去运行的代码!
- BEGIN 代码块
格式:BEGIN标签加上{}。
在这个代码块中完成一些变量的初始化操作,只在初始化时被运行一次。
eg.
awk定义FS变量为字段分隔符,在命令行 -F参数用于指定字段分割符,在BEGIN代码段中这样写:
fs.awk // awk 脚本,-f 参数引用脚本到awk命令中
BEGIN{
FS=":" // 将冒号赋给FS变量,改变字段分隔符
}
{
print "USER: " $1 "\tSHELL: " $7
}
head -n10 /etc/passwd |awk -f fs.awk
还可以在命令行直接初始化:
awk 'BEGIN{FS=":"}{print "USER: " $1 "\tSHELL: " $7}'
-F 和 FS 都可以改变字段分隔符,FS适用于awk脚本比较复杂的时候.
- END 代码块:
格式: END{}
所有输入处理完成后才去执行!仅仅执行一次!
END代码块中,awk脚本可以执行一些类似于统计数据、打印输出之类的操作。
eg.
search.awk
BEGIN{ # 初始化信息,便于阅读
print "How many prople with nologin?"
}
/nologin/ {++adder} # 核心awk处理过程
END{ # 扫尾工作,打印结果
print "'nologin' appears " adder " times."
}
awk -f search.awk /etc/passwd
- awk的模式匹配
针对BEGIN和END之间的第二部分的核心处理过程而言,只对匹配上的数据做处理!
语法:
/正则表达式/ {匹配后的操作}
awk首先用正则表达式去匹配数据记录,如果匹配上,才执行后面{}内的操作。
eg.1
awk '/^$/{print "This is an empty line."}' /etc/inittab # 匹配空行一次执行一次输出
eg.2
shell_recorder.wak
BEGIN{
print "SHELL USAGE:"
}
/bash/{++bash} //
/nologin/{++nologin}
END{
print "We have " bash " bash users."
print "We have " nologin " nologin users."
}
awk -f shell_recorder.awk /etc/passwd
awk变量
有两种:
用户自定义变量 、内建变量
- awk和绝大多数脚本语言一样,变量使用无需先声明,awk会在第一次使用该变量的时候自动建立变量。
- awk的变量建立时初始值都是空字符串,但是在需要数值时,它会被视为0。即awk会自动将字符串转换为数值进行计算。
在这一点上,awk的行为和shell脚本是一样的。大多数脚本是语言的行为都是这样:变量值存储字符串,当需要时再转换为为其他类型。
命名规则:
awk的变量名必须以
ASCII字母或
下划线开始,然后选择性的接上字母、数字、下划线。
- 如果用正则表达式来匹配变量名的话,awk的变量名必须匹配
[A-Za-z_][A-Za-z_0-9]*
命名建议: 局部变量小写,全局变量第一个字母大写,内建变量全部大写
awk 的常见内建变量
F-field字段,域 R-record记录 S-sign符号 N-number数字
awk数组
和awk变量一样,无需声明就能使用。
命名规则:和变量名的命名规则相同:[a-zA-Z_][a-zA-Z_0-9]*
数组元素的引用:
awk支持在数组名之后,以方括号将任意数字或字符串表达式扩起来作为引用数组的下标(索引)。其他语言要求数组的下标必须是数字。
eg.
site[google] = "
http://www.google.com"
site[yahoo] = "
http://yahoo.com"
(类似于键值对的形式,key是下标,value是数组元素)
awk这种能以任意值作为数组的索引(下标)的数组,称为关联数组,因为他们的
名称是与值相关联的。
- awk 支持数组的查找、插入、删除操作。
- awk数组的存储空间在引用新元素时会自动增长。
- awk数组的存储空间是稀疏的,插入了第一个元素array[1]后,可直接插入array[1000],不用填满2-999之间的数组元素。
- awk数组的元素值可以为任意类型,无类型限制。
总计:awk数组更像是一系列
键值对的集合,只不过打上了数组的标签。
数组的元素的删除:
delete array[index] //删除数组的某一个元素
delete array //删除数组所有元素
系统环境变量
awk支持访问linux系统环境变量,通过
ENVIRON数组
eg.
awk 'BEGIN{print
ENVIRON["HOME"]; print
ENVIRON["PATH"]}'
// 有两个索引是:ENVIRON["HOME"]、ENVIRON["HOME"]。
awk在启动时会从系统读取环境变量对数组ENVIRON进行初始化,可以对这个数组进行加入、删除以及修改。
算术运算和运算符
- 算术运算
awk中直接进行算术运算,
支持直接进行算术运算的运算符只有: +(加) -(减) *(乘) /(
除
) %(取模、求余) ^(幂次方),
例如:
awk 'BEGIN {print "(3+2)*7=" (3+2)*7}'
(3+2)*7=35
awk 'BEGIN {print "3^10=" 3^10}'
3^10=59049
% 是取模运算,表达式 x%y 中,运算结果是x%y的余数。当x能被y整除时,结果为0。
例如:判断闰年
year.txt
1936 图灵提出人类历史上第一个人工智能的概念
1946 世界上第一台计算机"埃尼阿克(ENIAC)"在美国宾西法尼亚大学诞生
1956 第二代计算机产生
1969 Ken.Thompso Dernis.Ritchie发布第一版Unix
1979 AT&T从各大学收回Unix版权,此后诞生了System V 和 BSD 两个版本线的Unix操作系统
1983 Richard Stallman创建GNU(GNU is not Unix.),1983-1991年GNU三大软件:Bash shell、gcc、emacs.
1991 Linus Torvalds发布Linux内核
1994 Lins 加入GNU,GNU系列软件与Linux内核结合,退出linus's minix,简称Linux.
leap.awk
# awk 脚本求闰年
BEGIN {
print "Pick leap years:"
}
{
# $1为记录的第一个字段
year=$1
if(( year % 4 == 0 && year % 100 != 0 )||year % 400 == 0)
print year "is a leap year."
else
print year "is not a leap year."
}
END {
print "Checking is over."
}
awk -f leap.awk year.txt
Pick leap years:
1936is a leap year.
1946is not a leap year.
1956is a leap year.
1969is not a leap year.
1979is not a leap year.
1983is not a leap year.
1991is not a leap year.
1994is not a leap year.
1995is not a leap year.
2016is a leap year.
Checking is over.
- awk运算符
= += -= *= /= ^= **= 赋值 # **= 等价于^=
?: c条件表达式 # 三目运算符,用法:x
>y?x:y 若x>y,则返回x,否则,返回y|| 逻辑或
&& 逻辑与
~ ~! 匹配正则表达式 不匹配正则表达式
< <= > >= != == 关系运算符
空格 连接
+ - 加 减
* / % 乘 除 求余
^ 求幂
++ -- 自加 自减
$ 引用字段
in 数组成员
+ - ! 一元加、减和逻辑非