Shell编程中linux文本处理三剑客之--awk
1.正则表达式的扩展
- awk,perl等还支持正则表达式扩展出来的一些元字符
- grep、sed不支持扩展正则表达式,egrep则支持
? | 匹配0个或1个在其之前的字符 |
---|---|
+ | 匹配一个或多个在其之前的字符 |
() | 表示一个字符集合或用在expr中 |
竖线 | 表示或,匹配一组可选的字符 |
1.“?”字符
- 匹配“?”符号之前的那个字符0次或1次
-
JO?B
#表示匹配O字符0次或1次,即匹配JOB或JOOB - 注意:“?”字符至多可以匹配1个字符
2.“+”字符
- 与“*”符号类似,都是匹配其前面的那个字符多次,但是“+”符号至少匹配1次,另一个可以匹配0次
-
S+EU
#表示匹配S1次或任意次,SSEU、SSSSEU等字符串都可由该表达式进行匹配,而SEU却不能由此来匹配
3.“()”符号和“ | ”符号
- “()”符号通常与“ | ”符号结合使用,表示一组可选字符的集合
-
re(a|e|o)d
#式中的(a|e|o)表示在字符a、e和o中任意选择一个字符,即read、reed、reod都可由该表达式进行匹配 -
re(a|e|o)等价于re[aeo]d
#“[ ]”符号能够替代“()”符号表示一组可选字符的集合 -
RE1 | RE2 | RE3
#“ | ”符号也可以表示多个正则表达式的“ 或 ”关系(RE1、RE2、RE3表示正则表达式)
2.awk概念
- awk其名称源于它的创始人Alfred Aho、Peter Weinberger和Brian Kernighan姓氏的首个字母
- awk拥有自己的语言:AWK程序设计语言,三位创建者已经将它正式定义为“样式扫描和处理语言”
- 允许创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能
- awk是一种很棒的语言,它时和文本处理和报表生成,其语法较为常见,借鉴了某些语言的一些精华,如C语言等。
- 在linux系统日常的工作处理中,发挥了很重要的作用
3.awk编程模型
- awk程序由一个主输入循环(Main input loop)维持
- 主输入循环反复执行,直到条件被触发
- 主输入循环无须由程序员去写,awk已经搭好主输入循环的框架
4.awk模式匹配
- 任何awk语言都由 模式(pattern)和动作(action) 组成
- 模式 是由一组用于测试输入行是否需要执行的规则
- 动作 是包含语句,函数和表达式的执行过程
- 简言之,模式决定动作何时触发和触发事件,动作执行对输入行的处理
- 第一种方式:
awk '/^$/{print "This is a blank line."}' file
^$是模式,{ }中的内容是动作,表示一旦读入的输入文件行是空行,就执行{ }中的动作 - 第二种方式:将命令写入文件中,然后调用
awk -f one.awk file
- 第三种方式:以脚本的方式执行awk命令
- 注意:与文件名无关,可以不加.awk后缀
5.记录和域
- awk认为输入文件时结构化的
- awk将每个输入文件行定义为记录,行中的每个字符串定义为域
- 域之间用空格,Tab键或其它符号进行分隔
- 分隔域的符号就叫分隔符
- awk定义域操作符$来指定执行动作的域
- 域操作符后面跟数字或变量来标识域的位置
- 每条记录的域从1开始编号,如$1表示第一个域,$0表示所有域
- 示例
1.$后加数字
-
awk '{print $2,$1,$4,$3}' file2
#输出第2,1,4,3域 -
awk '{print $0}' file2
#输出所有域
2.$加表达式 -
awk 'BEGIN {one=1;two=2} {print $(one+two)}' file2
#BEGIN:在完成操作前应该干的事,输出第三个域
3.awk输出默认为一个空格,Tab会被当成连续的空格处理
-
awk -F "\t" '{print $3}' file2
#指定Tab键为分隔域,动作为打印第3个域 -
awk -F "\t" '{print $1}' file2
#打印第1个域 -
awk -F "\t" '{print $2}' file2
#打印第2个域,为空
4.用+号,不管有多少个tab ,都看成一个tab键 -
awk -F "\t+" '{print $2}' file2
5.以“,”分隔 -
awk 'BEGIN {FS=","} {print $0}' file2
#以“,”为分隔符,打印全部 -
awk 'BEGIN {FS=","} {print $1,$3}' file2
#以“,”为分隔符,大意第1,3个域,因为数字与xian之间为空格,因此为一个域
6.关系和布尔运算符
- awk定义了一组关系运算符用于awk模式匹配
- 示例
1.匹配正则表达式
< | 小于 |
---|---|
> | 大于 |
<= | 小于或等于 |
>= | 大于或等于 |
== | 等于 |
!= | 不等于 |
~ | 匹配正则表达式 |
!~ | 不匹配正则表达式 |
-
awk 'BEGIN {FS=":"} $1~/root/' passwd
#匹配第1个域为root -
awk 'BEGIN {FS=":"} $0~/root/' passwd
#匹配所有的域中含有root的 -
awk 'BEGIN {FS=":"} $0!~/nologin/' passwd
#不匹配所有的域中含有nologin的
2.awk与条件语句(if if-else)
-
awk 'BEGIN {FS=":"} {if ($3<$4) print$0}' passwd
#如果第4个域小于第3个域,输出 -
多条件精确匹配
-
awk 'BEGIN {FS=":"} {if ($3==1||$4==10) print$0}' passwd
#第3个域为1或者第4个域为10
7.表达式
- awk表达式用于存储,操作和获取数据
- 一个awk表达式可由数值,字符常量,变量,操作符,函数和正则表达式自由组合而成
- 变量是一个值的标识符,定义awk变量非常方便,只需定义一个变量名并将值赋给它即可
- 变量名只能包含字母,数字和下划线,而且不能以数字开头
- 定义awk变量无须声明变量类型,每个变量由两种类型的值:字符串值和数值
- 变量的默认数值为0,默认字符串值为空
- 示例
1.统计file文件有多少空白行
-
awk '/^$/{print x++}' file
#统计由多少空白行,x++表示返回x值后x变量增加1,所以x初始值为0 -
awk '/^$/{print ++x}' file
#++x表示x变量先增加1再返回
2.平均值的计算
8.系统变量
- awk定义了很多内建变量用于设置环境信息,我们称之为系统变量
- 这些系统变量分为:
- 第一种用于改变awk的默认值,如域分隔符
- 第二种用于定义系统值,在处理文本时可以读取这些系统值,如纪录中的域数量,当前记录数,当前文件名等
NF | 记录的域数量 |
---|---|
NR | 显示当前的记录数 |
$0 | 表示打印记录的所有域 |
FILENAME | 保存了当前的输入文件名 |
-
注意: NR根据读取输入文件的进度而变化,读取第一条记录时,NR=1,读取到文件末尾时,NR为该文件所包含的记录数
9.格式化输出
- awk的一大主要功能时产生报表
- 报表就是要求按照一定的格式输出
- awk借鉴c语言的语法,定义了printf输出语句,它可以规定输出的格式
- 示例
1.分隔换行输出
-
awk 'BEGIN {FS=","} {printf("%s\t%d\n",$2,$8)}' file2
#从第2个域获取字符串,从第8个域获取整数,两个域之间用Tab键隔开,每输出两个域换行
2.awk的ascii字符与字符型字符的转换
awk 'BEGIN {printf("%c\n",65)}'
awk 'BEGIN {printf("%f\n",2020)}'
3.printf修饰符
-
awk 'BEGIN {FS=","} {printf("%-15s\t%s\n",$1,$3)}' file2
#以字符串格式输出文件的第1个域和第3个域,并对第1个域的字符串进行修饰 - -15表示该字符串长度控制为15位,并且左对其,若字符串不足15位则用空格补其
10.内置字符串函数
- awk提供了强大的内置字符串函数,用于实现文本的字符串替换,查找以及分隔等功能
1.gsub函数执行字符串替换功能,将第一个字符串替换为第二个字符串
-
awk 'BEGIN {FS=":";OFS=":"} gsub(/root/,"qaz",$1) {print $0}' passwd
#替换第1域上的root字符串 - OFS表示替换完成之后默认的输出的分隔域是什么,默认是空格
-
awk 'BEGIN {FS=":"} gsub(/root/,"qaz",$1) {print $0}' passwd
#默认空格输出 -
awk 'BEGIN {FS=":";OFS=":"} gsub(/root/,"qaz",$0) {print $0}' passwd
#替换所有的域上的root字符串
2.lindex返回第二个字符串在第一个字符串出现的首位置,length返回字符串的长度