前言
如果要格式化报文或从一个大的文本文件中抽取数据包,那么 a w k 可以完成这些任务。
表达式
有三种方式调用a w k,
第一种是命令行方式,如:
awk [-F field-separator] ‘commands’ input-files
commands 是真正的a w k命令。
[- F域分隔符]是可选的,因为 a w k使用空格作为缺省的域分隔符,
第二种是文件形式:
将所有 a w k命令插入一个文件,并使 a w k程序可执行,然后用 a w k命令解释器作为脚本的首行,以便通过键入脚本名称来调用它。
第三种方式是将所有的a w k命令插入一个单独文件,然后调用:
awk -f awk-scrippt-file input-files
域
awk可以安照一定的规则将文档分为n个域。
a w k执行时,其浏览域标记为 $ 1,$ 2 . . . $ n。这种方法称为域标识。使用这些域标识将更容易对域进行进一步处理。
使用$ 1 , $ 3表示参照第 1和第3域,注意这里用逗号做域分隔。如果希望打印一个有 5个域的记录的所有域,不必指明 $ 1 , $ 2 , $ 3 , $ 4 , $ 5,可使用$ 0,意即所有域。
例:
awk ‘{print $0}’ data.f
如果设置了- F 选项,则a w k每次读一条记录或一行,并使用指定的分隔符分隔指定域,但如果未设置- F选项,a w k假定空格为域分隔符,并保持这个设置直到发现一新行。当新行出现时,a w k命令获悉已读完整条记录,然后在下一个记录启动读命令,这个读进程将持续到文件尾或文件不再存在。
模式和动作
commmands 包含了模式和动作;
模式可以是任何条件语句或复合语句或正则表达式。
模式包括两个特殊字段 B E G I N和E N D。使用B E G I N语句设置计数和打印头。 B E G I N语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文件开始执行。 E N D语句用来在 a w k完成文本浏览动作后打印输出文本总数和结尾状态标志。
例:
awk ‘BEGIN {print “—————“ } {print $0}’ data.f
实际动作在大括号{ }内指明。动作大多数用来打印,但是还有些更长的代码诸如 i f和循环(l o o p i n g)语句及循环退出结构。如果不指明采取动作, a w k将打印出所有浏览出来的记录。
条件操作符与正则表达式
在 commmands 里用 if(表达式) 的形式使用条件操作符,常用条件操作符如下:
1 | 小于 |
在 commands 里用 ~/reg/ 的形式使用正则表达式,常用元字符如下:
1 | $ . [] | () * + ? |
匹配字符串
如果在f i e l d - 3中查询序号4 8,a w k将返回所有序号带4 8的记录:
awk ‘{if($3~/48/) print $0}’
精确匹配
为精确匹配4 8,使用等号= =,并用单引号括起条件。例如 $ 3 = =“4 8”,这样确保只有 4 8 序号得以匹配,其余则不行。
awk ‘$3==48 {print $0}’
关系匹配
输出所有级别为Ye l l o w或B r o w n的记录。
awk ‘$0~/Yello|Brown/‘
复合模式
复合模式或复合操作符用于形成复杂的逻辑操作,复杂程度取决于编程者本人。有必要了解的是,复合表达式即为模式间通过使用下述各表达式互相结合起来的表达式:
1 | AND : 语句两边必须同时匹配为真。 |
例:
1 | awk '{( $ 1 = = " P. B u n n y " & & $ 4 = = " Ye l l o w " ) print $0}' data.f |
awk 内置变量
a w k有许多内置变量用来设置环境信息。这些变量可以被改变。
1 | ARGC 命令行参数个数 |
要快速查看记录个数,应使用 N R,print NR放在E N D语法中。
awk ‘END {print NR}’ data.f
在从文件中抽取信息时,最好首先检查文件中是否有记录。下面的例子只有在文件中至少有一个记录时才查询 B r o w n级别记录。
awk ‘{if(NR>0 && $4~/Brown/) print $0}’
N F的一个强大功能是将变量 $ P W D的返回值传入a w k并显示其目录。这里需要指定域分隔符/。
1 | pwd |
awk 操作符
在a w k中使用操作符,基本表达式可以划分为数字型、字符串型、变量型、域及数组元素,前面已经讲过一些。
1 | = += *= / = %= ^ = 赋值操作符 |
输入域设置变量名
awk ‘{name=$1,belts=$4;if(belts~/Brown/)name”is belt”belts}’ data.f
域值比较操作
awk ‘{if($6 < 27)print $0}’ data.f
修改域值
源文本不会被修改,修改的是awk的缓存值。
awk ‘{if($1=”Yellow”) $6=$6-1; print $1, $6, $7}’ data.f
修改文本域即对其重新赋值。记住字符串要使用双秒号( “ “),并用圆括号括起整个语法。
awk ‘{if($1=”Yellow”) ($1=”Brown”); print $1}’ data.f
只显示修改记录
awk ‘{if($1=”Yellow”) {$1=”Brown”; print $1}}’ data.f
创建新的输出域
通常是根据原有域创建新的域,如 {$4 = $3 + $2};
awk ‘{if($6<$7) {diff=$7-$6; print $1,diff}}’ data.f
内置的字符串函数
a w k有许多强大的字符串函数
1 | gsub ( r, s ) 在整个$ 0中用s替代r |
例
awk ‘gsub(/4842/,4899) {print $0}’ data.f
awk ‘BEGIN {print index(“Bunny”,”ny”)}’ data.f
awk ‘{print length($1)}’ data.f
awk ‘BEGIN {print match(“ANCD”,/D/)}’ data.f
awk ‘{print substr($1,1,5)}’ data.f
printf函数
p r i n t f函数基本语法是p r i n t f([格式控制符],参数),格式控制字符通常在引号里。
1 | Width 域的步长,用0表示0步长 |
1 | \b 退格键 |
打印所有的学生名字和序列号,要求名字左对齐, 1 5个字符长度,后跟序列号。注意 \ n换行符放在最后一个指示符后面。输出将自动分成两列。
awk ‘{printf “%-15s %s/n”}’ data.f