Linux-AWK

如果要格式化报文或从一个大的文本文件中抽取数据包,那么awk可以完成这些任务。它在文本浏览和数据的熟练使用上性能优异

可以说awk是一种自解释的编程语言

为获取所需信息,文本必须格式化,需要用域分割符划分抽取域,分割符可以是任意字符

awk语言的最基本功能是在文件或字符串中基于指定规则浏览和抽取信息。awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息

9.1 调用awk

有三种方式调用awk

第一种是命令行方式

awk [-F field-separator] 'commands' input-file(s)
# commands是真正的awk命令
# 上面的例子中,[-F域分割符]是可选的,因为awk使用空格作为缺省的域分割符,因此如果要浏览域间有空格的文本,不必指定这个选项,但如果要浏览诸如passwd文件,次文件各域以冒号作为分割符,则必须指明-F选项。
awk -F: 'commands' input-file

第二种方式是将所有awk命令插入一个文件,并使awk程序可执行,然后用awk命令解释器作为脚本的首行,以便通过键入脚本名称来调用它

第三种方法是将所有的awk命令插入一个单独文件,然后调用:

awk -f awk-script-file input-files(s)
# -f选项指明在文件awk_script_file中的awk脚本,input_file(s)是使用awk进行浏览的文件名

9.2 awk脚本

在命令中调用awk时,awk脚本由各种操作和模式组成

如果设置了-F选项,则awk每次读一条记录或一行,并使用指定的分隔符分隔指定域

如果没有设置-F选项,awk假定空格为域分割符,并保持这个设置直到发现一新行

参照表,awk每次在文件中读一行,找到域分割符(这里是符号#),设置其为域n,直至一新行(这里是缺省记录分割符),然后,划分这一行作为一条记录,接着awk再次启动下一行读进程

awk读文件记录的方式
域1分隔符域2分隔符域3分隔符域4及换行
P.Bunny(记录1)#02/99#48#Yellow\n
J.Troll(纪录2)#07/99#4842#Brown-3\n

9.2.1 模式和动作

任何awk语句都由模式和动作组成。在一个awk脚本中可能有许多语句。模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。如果省略模式部分,动作将时刻保持执行状态

 模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段:BEGIN和END。使用BEGIN语句设置计数和打印头。BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文件开始执行。END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态标志。如果不特别指明模式,awk总是匹配或打印行数

实际动作在大括号{}内指明。如果不指明采取动作,awk将打印出所有浏览出来的记录

9.2.2 域和记录

awk执行时,其浏览域标记为$1,$2...$n。这种方法称为域标识

使用$1,$3表示参照第1域和第3域,注意这里用逗号做域分隔。

如果希望打印一个有5个域的记录的所有域,不必指明$1,$2,$3,$4,$5,可使用$0,意即所有域。awk浏览时,到达一新行,即假定到达包含域的记录末尾,然后执行新纪录下一行的读动作,并重新设置域分隔。注意执行时不要混淆符号$和shell提示符$,他们是不同的

为打印一个域或所有域,使用print命令。这是一个awk动作(动作语法用圆括号括起来)

2.保存awk输出

有两种方法保存shell提示符下awk脚本的输出

最简单的方式是使用输出重定向符号 >文件名

# 重定向输出到文件wow
$ awk '{print $0}' grade.txt >wow
# 使用这种方法要注意,显示屏上不会显示输出结果。因为它直接输出到文件。只有在保证输出结果正确时才会使用这种方法。它也会重写硬盘上同名数据

第二种方法是使用tee命令,在输出到文件的同时输出到屏幕。在测试输出结果正确与否时多使用这种方法

# 例如输出重定向到文件 delete_me_and_die,同时输出到屏幕
# 使用这种方法,在awk命令结尾写入| tee delete_me_and_die
$ awk '{print $0}' grade.txt | tee delete_me_and_die

3. 使用标准输入

实际上任何脚本都是从标准输入中接受输入的

1、使用awk脚本输入文件格式:
$ belts.awk grade_student.txt

2、使用重定向方法:
$ belts.awk < grade2.txt

3、使用管道方法:
$ grade2.txt | belts.awk

4、打印所有记录
$ awk '{print $0}' grade.txt
awk读每一条记录。因为没有模式部分,只有动作部分{print $0}(打印所有记录),这个动作必须用花括号括起来。上述命令打印整个文件

5、打印单独记录
假定只打印学生名字和腰带级别,通过查看域所在列,可知为field-1和field-4,因此可以使用$1和$4,但不要忘了加逗号以分隔域
$ awk '{print $1,$4} grade.txt'

6、打印报告头
为加入tab键,使用tab键速记引用符\t
本例中加入name和belt及下划线。下划线使用\n,强迫启动新行,并在\n下一行启动打印文本操作
打印信息头防止在BEGIN模式部分,因为打印信息头被界定为一个动作,必须用大括号括起来
在awk查看第一条信息前,信息头被打印
$ awk 'BEGIN {print "Name    Belt\n---------"}{print $1"\t"$4}' grade.txt

7、打印信息尾
在末行加入end of report信息,可使用END语句
END语句在所有文本处理动作执行完之后才被执行
END语句在脚本中的位置放置在主要动作之后
下面简单打印头信息并告之查询动作完成
$ awk 'BEGIN {print "Name\n----------"} {print $1} END {"end-of-report"}'

8、awk错误信息提示
在命令中碰到一些错误时,awk将试图打印错误行,但由于大部分命令都只在一行,因此帮助不大
在碰到awk错误时,可相应查找
    确保整个awk命令用单引号括起来
    确保命令内所有引号成对出现
    确保用花括号括起动作语句,用圆括号括起条件语句
    可能忘记使用花括号,也许你认为没有必要,但awk不这样认为,将按之解释语法

9、awk键盘输入
如果在命令行并没有输入文件grade.txt,将会怎样?
BEGIN部分打印了文件头,但awk最终停止操作并等待,并没有返回shell提示符
这是因为awk期望获得键盘输入。因为没有给出输入文件,awk假定下面会给出
如果愿意,顺序输入相关文本,并在输入完成后敲<Ctrl-D>键
如果敲入了正确的域分割符,awk会像第一个例子一样正常处理文本

9.2.3 awk中正则表达式及其操作

这里正则表达式用斜线括起来。例如,在文本文件中查询字符串Green,使用/Green/可以查出单词Green的出现情况

9.2.4 元字符

这是awk中正则表达式匹配操作中经常用到的字符

\ ^ $ . [] | () * + ?
#其中+和?只适用于awk
+ 使用+匹配一个或多个字符
? 匹配模式出现频率。例如使用/XY?Z/匹配XYZ或YZ

9.2.5 条件操作符

awk条件操作符
操作符描述
<小于
<=小于等于
==等于
!=不等于
>=大于等于
~匹配正则表达式
!不匹配正则表达式
1、匹配
为使一域号匹配正则表达式,使用符号‘~’后紧跟正则表达式,也可以用if语句。awk中if后面的条件用()括起来
如果只要打印brown腰带级别可知其所在域为field-4,这样可以写出表达式
{if($4~/brown/)print}
意即如果field-4包含brown,打印它。如果条件满足,则打印匹配记录行
可以编写下面脚本,因为这是一个动作,必须用花括号{}括起来
$ awk '{if($4~/Brown/) print $0}' grade.txt
匹配记录找到时,如果不特别声明,awk缺省打印整条记录

下面例子意即如果记录包含模式brown,就打印它
$ awk '$0 ~ /Brown/ ' grade.txt

2、精确匹配
假定要使字符串精确匹配,比如说查看学生序号48,文件中有许多学生序号包含48,如果在field-3中查询序号48,awk将返回所有序号带48的记录:
$ awk '{if($3~/48/) print $0}' grade.txt

为精确匹配48,使用等号==,并用单引号括起条件。例如$3=="48",这样确保只有48序号得以匹配
$ awk '$3=="48" {print $0}' grade.txt

3、不匹配
有时要浏览信息并抽取不匹配操作的记录,与~相反的符号是!~,意即不匹配。像原来使用查询brown腰带级别的匹配操作一样,现在看看不匹配情况。表达式$0!~/brown/,意即查询不包含模式brown腰带级别的记录并打印它
缺省模式下,awk将打印所有匹配记录,因此这里不必加入动作部分
$ awk '$0 !~ /Brown/' grade.txt

可以只对field-4进行不匹配操作
$ awk '{if{$4!~/Brown/} print $0}' grade.txt

如果想要查询非brown-2的腰带级别
$ awk '$4 != "Brown-2" {print $0}' grade.txt

4、小于
判断目前级别分,field-6是否小于最高分field-7
$ awk '{if ($6 < $7) print $0 "$1 Try better ai the next comp"}' grade.txt

5、小于等于
对比小于、小于等于是在操作符上做些小改动
$ awk '{if ($6 <= $7) print $1}' grade.txt

6、大于
$ awk '{if ($6 > $7) print $1}' grade.txt

7、设置大小写
为查询大小写信息,可使用[]符号。在测试正则表达式时提到可匹配[]内任意字符或单词,因此若查询文件中级别为green的所有记录,不论其大小写,表达式应为'/[Gg]reen/'
$ awk '/[Gg]reen/' grade.txt

8、任意字符
抽取名字,其记录第一域的第四个字符是a,使用句点.。表达式/^...a/意为行首前三个字符任意,第四个是a,尖角符号代表行首
$ awk '$1 ~/^...a/' grade.txt

9、或关系匹配
为抽取级别为yellow或brown的记录,使用竖线符|。意为匹配|两边模式之一
注意,使用竖线符时,语句必须用圆括号括起来
$ awk '$0~/(Yellow|Brown)/' grade.txt
上面例子为输出所有级别为Yellow或Brown的记录

使用这种方法在查询级别为Green和green时,可以得到与使用[]表达式相同的结果
$ awk '$0~/(Green|green)/' grade.txt

10、行首
不必总是使用域号。如果查询文本文件行首包含48的代码,可简单使用下面^符号
$ awk '/^48/' input-file

复合模式或复合操作符用于形成复杂的逻辑操作,复合表达式即为模式间通过使用下述各表达式互相结合起来的表达式

&& AND : 语句两边必须同时匹配为真
|| OR : 语句两边同时或其中一边匹配为真
! 非 求逆

11、AND
打印记录,使其名字为P.Bunny且级别为YEllow,使用表达式($1=="P.Bunny"&&$4=="Yellow"),意为&&两边匹配均为真
$ awk '{if ($4=="Yellow" || $4~/Brown/) print $0}' grade.txt

12、OR
如果查询级别为Yellow或Brown,使用或命令。意为“||”符号两边的匹配模式之一或全部为真
$ awk '{if ($4=="Yellow" || $4~/Brown/) print $0}' grade.txt

9.2.6 awk内置变量

awk有许多内置变量用来设置环境信息。这些变量可以被改变

awk内置变量
ARGC命令行参数个数
ARGV命令行参数排列
ENVIRON支持队列中系统环境变量的使用
FILENAMEawk浏览的文件名
FNR浏览文件的记录数
FS设置输入域分隔符,等价于命令行-F选项
NF浏览记录的域个数
NR已读的记录数
OFS输出域分隔符
ORS输出记录分隔符
RS控制记录分隔符
1、ARGC
支持命令行中传入awk脚本的参数个数

2、ARGV
是ARGC的参数排列数组,其中每一元素表示为ARGV[n],n为期望访问的命令行参数

3、ENVIRON
支持系统设置的环境变量,要访问单独变量,使用实际变量名
eg ENVIRON["editor"]="Vi"

4、FILENAME
支持awk脚本实际操作的输入文件。因为awk可以同时处理许多文件,因此如果访问量这个变量,将告知系统目前正在浏览的实际文件

5、FNR
支持awk目前操作的记录数。其变量值小于等于NR。如果脚本正在访问许多文件,每一新输入文件都将重新设置此变量

6、FS
用来在awk中设置域分隔符,与命令行中-F选项功能相同。缺省情况下为空格。如果用逗号来作域分隔符,设置FS=“,”

7、NF
支持记录域个数,在记录被读之后再设置

8、OFS
允许指定输出域分隔符,缺省为空格。如果想设置为#,写入OFS="#"

9、ORS
为输出记录分隔符,缺省为新行(\n)

10、RS
是记录分隔符,缺省为新行(\n)

9.2.7 NF、NR和FILENAME

1、NR
到处一个数据库文件后,如果想要快速浏览记录个数,以便对比于其初始状态,查出导出过程中出现的错误。使用NR将打印输出文件的记录个数。print NR 放在END语法中
$ awk 'END {print NR}' grade.txt

2、NF
所有学生记录被打印,并带有其记录号。使用NF变量显示每一条读记录中有多少个域,并在END部分打印输入文件名
$ awk '{print NF,NR,$0}END{print FILENAME}' grade.txt

3、在从文件中抽取信息时,最好首先检查文件中是否有记录
下面的例子只有在文件中至少有一个记录时才查询Brown级别记录。使用AND复合语句实现这一功能。意即至少存在一个记录后,查询字符串Brown,最后打印结果
$ awk '{if (NR >0 && $4~/Brown/) print $0}' grade.txt

4、NF的一个强大功能是将变量$PWD的返回值传入awk并显示其目录。这里需要指定域分隔符/
$ pwd
$ echo $pwd | awk -F/ '{print $NF}'

另一个例子是显示文件名
$ echo "/user/local/etc/rc.sybase" | awk -F/ '{print $NF}'

9.2.8 awk操作符

在awk中使用操作符,基本表达式可以划分为数字型、字符串型、变量型、域及数组元素

= += *= / = %= ^ =赋值表达式
条件表达操作符
|| && !并、与、非
~!~匹配操作符,包括匹配和不匹配
< <= == != >>关系操作符
+ - * / %  ^算术操作符
+ + --前缀和后缀

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值