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}'