awk

http://pengzhenloveseo.blog.163.com/blog/static/163156529201072535047651/

1、$0变量:它指的是整条记录。如$ awk '{print $0}' test将输出test文件中的所有记录。

2、变量NR:一个计数器,每处理完一条记录,NR的值就增加1。如$ awk '{print NR,$0}' test将输出test文件中所有记录,并在记录前显示记录号。

3、内建变量FS保存输入域分隔符的值,默认是空格或tab。我们可以通过-F命令行选项修改FS的值。如$ awk -F: '{print $1,$5}' test将打印以冒号为分隔符的第一,第五列的内容。

可以同时使用多个域分隔符,这时应该把分隔符写成放到方括号中,如$awk -F'[:\t]' '{print $1,$3}' test,表示以空格、冒号和tab作为分隔符。

4、匹配操作符(~)和不匹配操作符(!~),用来在记录或者域内匹配正则表达式。如$ awk '$1 ~/^root/' test将显示test文件第一列中以root开头的行。$ awk '$1!~/^root/' test将显示test文件第一列中不以root开头的行!

5、复合表达式语法:(compound expression)

(expr1)&& (expr2)  ------- 与

(expr1)|| (expr2)  ------- 或

说明一下:符合表达式必须用括号括起来

当使用&&时,expr1和expr2必须同时为零(零代表真!呵呵~),复合表达式才为真;

当使用 || 时,expr1和expr2 只要有一个为真,复合表达式则为真!

6、举例:vi data.f(每列后是tab)

48Dec3BC1997LPSX68.00LVX2A138

483Sept5Ap1996USP65.00LVX2C189

47Oct3ZL1998LPSX43.00KVM9D512

219dec2CC1999CAD23.00PLV2C68

484nov7PL1996CAD49.00PLV2C234

483may5PA1998USP37.00KVM9D644

216 sept    3ZL1998 USP 86.00   KVM9E   234

下面的例子重定向输出到新文件:

awk'{print$0}'data.f>data.f.1

使用tee命令,在输出到文件的同时输出到屏幕:

awk'{print$0}'data.f|teedata.f.2

打印信息头放置在BEGIN模式部分:

awk'BEGIN{print"NameBelt\n---------------"}{print$1"\t"$4}'data.f

打印信息尾。END语句在所有文本处理动作执行完之后才被执行。END语句在脚本中的位置放置在主要动作之后:

awk 'BEGIN {print "Name Belt\n---------------"}{print $1"\t"$4} END {print "end-of-report"}' data.f

为使一域号匹配正则表达式,使用符号‘~’后紧跟正则表达式,也可以用i f语句。awk中i f后面的条件用()括起来。

如果第1域匹配483的话就把该记录打印出来:

awk'{if($1~/483/)print$0}'data.f

完成同一目的也可以这样写:

awk'$0~/483/'data.f

为精确匹配48,使用等号==,并用单引号括起条件:

awk'{if($1=="48")print$0}'data.f

有时要浏览信息并抽取不匹配操作的记录,与~相反的符号是!~,意即不匹配:

awk'{if($1!~/483/)print$0}'data.f

完成同一目的也可以这样写:(缺省情况下,awk将打印所有匹配记录)

awk'$0!~/483/'data.f

为查询大小写信息,可使用[]符号。在测试正则表达式时提到可匹配[]内任意字符或单词:

awk'/[lL]PSX/'data.f

抽取名字,其记录第3域的第3个字符是L,使用句点.

awk'$3~/^..L/'data.f

使用竖线符|意为匹配|两边模式之一。注意,使用竖线符时,语句必须用圆括号括起来:

awk'$0~/(USP|LPSX)/'data.f

复合表达式,&&AND,||OR,!非:

awk '{if($1=="483" && $2~/^Sept/) print $0}' data.f

要快速查看记录个数,应使用NR。print NR放在E N D语法中:

awk'END{printNR}'data.f

使用NF变量显示每一条读记录中有多少个域,并在END部分打印输入文件名:

awk'{printNR,NF,$0}END{printFILENAME}'data.f

至少存在一个记录后,查询字符串USP,最后打印结果:

awk'{if(NR>0&&$4~/USP/)print$0}'data.f

NF的一个强大功能是将变量$PWD的返回值传入awk并显示其目录。这里需要指定域分隔符/

echo $PWD | awk -F/ '{print $NF}'

设置输入域到域变量名:

awk'{no=$1;month=$2;if(no=="48")printno"monthis"month}'data.f

修改数值域取值:

awk'{if($1=="48")$5=$5-10;print$1,$5,$6}'data.f

修改文本域:(要记住实际输入文件是不可修改的,修改的只是保存在缓存里的awk复本。awk会在变量NR或NF变量中反映出修改痕迹。)

awk'{if($2=="Dec")$2="December";print$0}'data.f

只显示修改记录:

awk'{if($2=="Dec"){$2="December";print$0}}'data.f

创建新的输出域:

awk'BEGIN{print"No\tMonYear"}{if($2~/[Ss]ept/){$8=$5-$7;print$2,$8}}'data.f

awk'BEGIN{print"No\tMonYear"}{if($2~/[Ss]ept/){diff=$5-$7;print$2,diff}}'data.f

列值增加很有用。许多文件都要求统计总数:

awk'(tol+=$5);END{print"Totalmoney:"tol}'data.f

如果文件很大,你只想打印结果部分而不是所有记录,在语句的外面加上大括号{}即可:

awk'{(tol+=$5)};END{print"Totalmoney:"tol}'data.f

快速查看所有文件的长度及其总和,但要排除子目录:

ls-l|awk'/^[^d]/{print$9"\t"$5}{tol+=$5}END{print"TotalKB:"tol}'

相关推荐