上一篇总结了下sed的用法,这一篇玩玩sed的好基友awk,学完它俩,以后就再也不用怕处理文本文件了。
awk其实和sed处理过程差不多,都是面向字符流的。sed和awk都相当于是一个加工厂,输入的文本行,相当于原材料,原材料在工厂中经过一系列处理。然后输出成品。
awk和sed不同的是,awk更加的强大了,基本上可以说大多数sed能够实现的功能,awk都可以实现。。。。
但是实现相同的功能,大多情况下sed的过程更加的简洁吧。
当然awk还有着更多的功能,awk本身就是一门类C的语言了,有变量,有流程控制,有函数。可以针对单行,多行,字段等进行更多的处理。
OK,先说说awk的架构吧
架构
awk脚本,可以说由三个例程组成。
例程长什么样的呢?
长这样的:模式{}
模式用于匹配,{}里面的东西,是对匹配成功的东西,处理的过程
OK,看看是哪三个吧?
awk ‘BEGIN{} /正则/{} END{}‘ file
当然这三类例程,每类例程都是可选的,可以不出现,出现一次,或多次都可以。
BEGIN{}:BEGIN规则相关的例程,处理输入前将做的处理。 这个例程是不读取文件输入行的,从上面 的图中可以看到
/正则/{}:主输入循环例程,处理输入过程中将做的处理。这个例程其实就是awk为我们封装好的一个循环框架,循环变量是满足匹配模式的行,循环终止条件是所有匹配的行都处理完了。所以循环的次数和匹配的行数相同,无输入或无匹配的行,循环将不执行。。如果没有/正则/这种模式匹配,则所有输入行都执行循环
END{}:END规则相关的例程,处理输入后将做的处理。这个例程主要做些扫尾的工作,比如主输入循环中的最后的结果,在END{}中输出
画个图,看一下三个例程的执行过程。
OK,我们再看看三个例程的变量,是怎么用的
看到了吧,这三个小例子说明了,
1.前面例程定义的变量,在该例程执行完毕后,变量并不会消失,而是可以被后续的例程继续使用。
2.后面例程定义的变量,前面的例程却不可以使用的。这个想想也就明白了,你前面的例程都执行完毕了,我后面的变量还没定义呢,你怎么能使用我的变量呢?
记录和字段
说到底awk主要还是要用来处理文本文件,我们最应该关注的还是主输入循环例程,而BEGIN和END,则可以让我们的处理过程更加的灵活强大
OK,来看看什么是记录和字段吧
记录:就是我们输入文本的每一行,就叫做一条记录。在awk中可以用$0这个变量表示
字段:就是我们每条记录按照特定的分隔符去分割,分割后每个小片段就是一个字段,用$1,$2,...表示
OK,说到字段,字段的划分是绕不过的一个话题。
看一下,怎么选定分隔符去划分字段吧,一共有两种方法去划分字段。
第一种方法使用-F参数,举个小例子
分割符可以用图中的几种方式去表示
默认情况下为空格或制表符
可以指定分割符为某一字符,加在-F参数的后面,可以紧挨着-F,用‘‘或""括起来
可以用正则表达式来,表示分隔符
可以指定多个分割符
第二种方法,使用awk提供的一个系统变量FS,翻译成英文是field segmentation,意思就是字段分割
OK,看一下怎么用
使用FS这个系统变量指定分割符的时候,分隔符的形式和-F参数的那四种形式是一样的。。。
不过我们一般把FS变量,定义在BEGIN例程中,当然也可以在命令行的-v参数后面。
注意:我们上面讲的字段分割,如果在记录的最开头和最结尾出现分割符,会被awk忽略的
说完了记录和字段,输入这一块就差不多了,记录输入之后,就是处理的过程了。这也是主输入循环例程,主要干的活
主输入循环的处理过程,主要由语句,函数和表达式组成的了
表达式
表达式可以用来存储,操作和检索数据。一个表达式,通过计算一个返回值。
表达式由数字,字符串常量,变量,操作符,函数和正则表达式组成。
这里先主要说说,常量,变量,操作符。。函数下一篇说
常量
awk中的常量有两种,一个数字,二是字符串。一般用‘‘或者""括起来,
注意:命令行上使用字符串,要用"",避免shell的影响
字符串中,可以使用转义字符
\a,\b,\f,\n,\r,\t,\v,\ddd,\xbex,\c
变量
awk的变量和别的语言的变量有些不同。
1.awk的每个变量都有,字符串型值和数字型值。awk能够根据表达式的前后关系,来自动的选取合适的值。
2.变量不必初始化,awk会自动把它们初始化为空字符串,如果作为数字,值则为0
如awk ‘BEGIN{print a}‘ ,结果为空
操作符
算术操作符
+,-,*,/,%,^(取幂)
赋值运算符
++,--,+=,-=,*=,/=,%=,^=
关系操作符和布尔操作符主要用于两个表达式之间的比较
关系操作符
<,>,<=,>=,==,!=,~(匹配),!~(不匹配)
布尔操作符
||
&&
!
系统变量
变量名 | 用途 |
FS(Field segmentation)(可改变) | 域分隔符,默认为空格或制表符,可自定义为任意单个或多个字符,及正则表达式 |
OFS(output Field segmentation)(可改变) | 和FS等效的输出域分隔符,默认为空格 |
NF(Number Fields)(不要改变) | 当前输入记录的字段个数,最好不要人为的去改变这个值 |
RS(Record segmentation)(可改变) | 记录分隔符,默认为一个换行符。在处理多行记录的时候,我们可能会把RS的值,改变 |
ORS(output Record segmentation)(可改变) | 和RS对应的输出记录分隔符,它的默认值也是一个换行符 |
FILENAME(不要改变) | 输入文件的名称 |
NR(Number Record)(不要改变) | 当前输入记录的编号,可以跨越多个文件 |
FNR(File Numberr Record)(不要改变) | 当前文件记录的编号,跨文件的话,会重新从0开始 |
ARGC(不要改变) | 命令行参数个数 |
ARGV(不要改变) | 命令行参数数组 |
OFMT | 控制数字到字符串转换,这个适合楼主的环境(mawk),现在不适合gawk了。。。。gawk用CONVFMT |
ENVIRON | UNIX环境变量 |
ERRNO | UNIX系统错误消息 |
IGNORECASE | 如果为真,则忽略大小写的匹配 |
RSTART | 被匹配函数,匹配的字符串首 |
RLENGTH | 被匹配函数的字符串长度 |
SUBSEP | \034 |
这么多系统变量,其实前10个会被经常用到。。。后面那几个,咱们平时分析个日志,基本上不会用到这些东西,在这里mark下,就不细说了。
第一组:FS,OPF,NF 这三个变量,都是针对字段的,看个例子
第二组:RS,ORS,NR,FNR这四个变量,都是针对记录的,看个例子
其它的都用处不大,就不细究了。
格式化打印
和c语言中的printf一样。
print和printf相比有啥优点呢?
唯一的优点就是,print是自动换行的,而printf要自己加\n,参数才能换行
printf语法格式
printf (for mat-expression [,arguments])
printf格式说明符
c,d,i,e,E,f,g,G,O,s,u,x,X,%
最常用的就仨,%d(数字),%s(字符串),%f(浮点数)
宽度和精度
格式:%宽度.精度 格式说明符
举个例子大伙就知道怎么用了
命令行参数
两种方法:
看个例子
注意:
当使用awk -v var=argument时候,变量首先就会被传递给BEGIN相关的例程
而使用awk ‘‘ var=argument的时候,变量在BEGIN例程中是不可用的。
这是为什么呢?
因为后面传递过来的参数,就像文件一样被处理,赋值操作直到主循环例程开始执行时,才会发生。
本文出自 “西风” 博客,请务必保留此出处http://lixcto.blog.51cto.com/4834175/1438100
原文:http://lixcto.blog.51cto.com/4834175/1438100