细说awk

Awk将读入的每行,通过定界符(默认空格,可由-F指定),将该行分隔成每个),利用 $1$2$3 ... 表示第一段,第二段,第三段...;利用 $0 表示整行。

Awk 程序更像是一种查询语言

awk规则:

1,(指令),由 模式+过程 组成,必须单引号 ' ' 括起来。

2,(模式),即正则表达式,必须斜杠 / / 括起来。

3,(过程),即动作print等,必须大括号 { } 括起来。

例子:list文件

John Daggett, 341 King Road, Plymouth MA

Alice Ford, 22 East Broadway, Richmond VA

Orville Thomas, 11345 Oak Bridge Road, Tulsa OK

Terry Kalkas, 402 Lans Road, Beaver Falls PA

Eric Adams, 20 Post Road, Sudbury MA

Hubert Sims, 328A Brook Road, Roanoke VA

Amy Wilde, 334 Bayshore Pkwy, Mountain View CA

Sal Carpenter, 73 6th Street, Boston MA

小问题1:列出所有MA州的人员的姓名及他们的住所地址。

$ awk  -F,  '/MA/{print$1 ; print $2}'  list  //(像不像Mysql 查询语言?)打印结果:

John Daggett

 341 King Road

Eric Adams

 20 Post Road

Sal Carpenter

 73 6th Street

小问题2:用全名替换简写名,如California 替换 CA

nameds.sed文件(注意,存储的是sed的命令集,而不是awk的指令集,从指令的形式上就可以看出来了)

s/ CA/, California/

s/ MA/, Massachusetts/

s/ OK/, Oklahoma/

s/ PA/, Pennsylvania/

s/ VA/, Virginia/

$ sed -f s.sed list1  //打印结果:

John Daggett, 341 King Road, Plymouth, Massachusetts

Alice Ford, 22 East Broadway, Richmond, Virginia

Orville Thomas, 11345 Oak Bridge Road, Tulsa, Oklahoma

Terry Kalkas, 402 Lans Road, Beaver Falls, Pennsylvania

Eric Adams, 20 Post Road, Sudbury, Massachusetts

Hubert Sims, 328A Brook Road, Roanoke, Virginia

Amy Wilde, 334 Bayshore Pkwy, Mountain View, California

Sal Carpenter, 73 6th Street, Boston, Massachusetts

$ sed  -f  nameds.sed  list  |  awk  -F,  '{print $4}'  //sed结果通过 管道 做为awk的输入。打印结果:

 Massachusetts

 Virginia

 Oklahoma

 Pennsylvania

 Massachusetts

 Virginia

 California

 Massachusetts

$ sed  -f  names.sed  list  |  awk  -F,  '{ print $4 ", " $0}'  //打印结果:

 Massachusetts, John Daggett, 341 King Road, Plymouth, Massachusetts

 Virginia, Alice Ford, 22 East Broadway, Richmond, Virginia

 Oklahoma, Orville Thomas, 11345 Oak Bridge Road, Tulsa, Oklahoma

 Pennsylvania, Terry Kalkas, 402 Lans Road, Beaver Falls, Pennsylvania

 Massachusetts, Eric Adams, 20 Post Road, Sudbury, Massachusetts

 Virginia, Hubert Sims, 328A Brook Road, Roanoke, Virginia

 California, Amy Wilde, 334 Bayshore Pkwy, Mountain View, California

 Massachusetts, Sal Carpenter, 73 6th Street, Boston, Massachusetts

初级问题3:按州的名字排序并列出州的名字,以及所有住在那个州的人的姓名?

以问题2的结果作为管道的输入,

管道输出到awk.sh脚本文件:

#! /bin/sh

awk -F, '{ print $4 ", " $0 }' | sort | awk -F,

'$1==LastState { print "\t" $2 }

$1!=LastState {

LastState=$1

print $1

print "\t" $2

}'

这里注意四个小问题,1chomdawk.sh权限;2./awk.sh 执行;3,第一个awk的输入文件 $* 可要可不要,为什么? 4,在awk中,变量无需初始化,直接写上去即可使用,默认初始值整型为0字符串型为空

$ sed  -f  names.sed  list1  |  ./awk.sh  //打印结果:

 California

 Amy Wilde

 Massachusetts

 Eric Adams

 John Daggett

 Sal Carpenter

 Oklahoma

 Orville Thomas

 Pennsylvania

 Terry Kalkas

 Virginia

 Alice Ford

 Hubert Sims

小问题4ipbaby项目上遇到过,以前觉得无从下手,现在a piece of cake !

H264_frame1.5Mps文件内容:

H264 NAL units(nalcount=3,nalsize=46941)

H264 NAL units(nalcount=1,nalsize=10014)

H264 NAL units(nalcount=1,nalsize=6360)

H264 NAL units(nalcount=1,nalsize=3245)

H264 NAL units(nalcount=1,nalsize=3746)

......

要求:提取nalsize后面的数字,单独放在一个文件中。(方便直接拷入excel作图)

结果重定向到datah264中,答案有很多,以下是其中两种:

$ sed  's/)//'  ./H264_frame1.5Mps | awk  -F=  '{print $3}'  >  datah264

或者写个shell脚本:my.sh

#!/bin/sh

 sed  's/)//'  $*  |  awk  -F=  '{print $3}'  >  datah264

$ ./my.sh  ./H264_frame1.5Mps 

注意:my.sh脚本中的 $* 表示命令行中的 “./H264_frame1.5Mps”参数字符串。

小问题5:提取H264_frame1.5Mps 文件中的括号内的内容?

按前面的思路,用sed ‘)’ 消除,然后awk在以 ‘(‘ 分隔:

$ sed  '/)//'  h264_frame1.5mps  |  awk  -F(  '{print $2}'

bash: syntax error near unexpected token `('

出错!

不认识’(’,好吧,由于我知识有限,目前为快速达到目标,绕过它就是了:

$ sed -e 's/)//'  -e 's/(/,/'  h264_frame1.5mps | awk  -F,  '{print $2"," $3}'

输出:

nalcount=3,nalsize=46941

nalcount=1,nalsize=10014

nalcount=1,nalsize=6360

nalcount=1,nalsize=3245

nalcount=1,nalsize=3746

如果我知道转义能使’)’成为awk的分隔符,那么为什么不这样?

$ awk -F[\(\)]  '{print $2}'  h264_frame1.5mps

输出:同样结果

其中[]内同时指定了两个分隔符,’(’和’)’,提取$2就可以了!

这样,对于小问题4,有更简单的方法:

$ awk  -F[\(\)=]  '{print $4}'  h264_frame1.5mps

输出:

46941

10014

6360

3245

3746

Awk小结:

$ awk  [ -Fre]  [-f progfile]  ['prog']  [parameter...]  [in_file]

参数说明:

-Fre:允许awk更改其字段分隔符(其中re的格式为 "pattern" 

 -F[\(\)=] 等价于 -F"[\(\)=]" 等价于 -F"\(|\)|="

-f progfile:允许awk调用并执行progfile指定有程序文件progfile是一个文本文件,他必须符合awk的语法。jsf,存储awk的指令 /pattern/ {action} 

'prog':  awk的程序语句段。这个语句段必须用单拓号:''括起,以防被shell解释。这个程序语句段的标准形式为:

'/pattern/ {action}'

其中参数pattern可以是egrep正则表达式中的任何一个,它可以使用语法/re/再加上一些样式匹配技巧构成。与sed类似,你也可以使用"," 分开两样式以选择某个范围。关于匹配的细节,你可以参考附录,如果仍不懂的话,找本UNIX书学学grepsed(本人是在学习ed时掌握匹配技术的)。参数action总是被大括号包围,它由一系列awk语句组成,各语句之间用";"(或回车)分隔。awk解释它们,并在pattern给定的样式匹配的记录上执行其action操作。与shell类似,你也可以使用“#”作为注释符,它使“#”到行尾的内容成为注释,在解释执行时,它们将被忽略。你可以省略patternaction之一,但不能两者同时省略,当省略pattern时没有样式匹配,表示对所有行(记录)均执行action操作,省略action时执行缺省的操作——在标准输出上显示。

parameter: 该参数帮助为不同的变量赋值。格式 var=value ,注意等号两边不能有空格,除非空格是varvalue的一部分。$ awk  -f  progfile  n=1  test1  n=2  test2  参数同输入文件test12一样,会在BEGIN 执行以后再解析。处理过程是:以输入文件分隔,先单独处理完 n=1  test1两个输入(如同没有 n=2  test2 参数一样),处理完成后,(如同没有n=1  test1 参数样)再处理 n=2  test2 。问题是,对两个输入文件,BEGIN 会执行两次吗?测试是仅执行一次。

如果想要在shell可执行程序或命令行中传递的参数再 BEGIN 执行前解析,可以使用 -v选线,例如 $ awk  -v  var=9  -f  progfile  n=1  test1  n=2  test2  varBEGIN之前解析。

in_file:awk的输入文件,awk允许对多个输入文件进行处理。值得注意的是awk不修改输入文件。如果未指定输入文件,awk将接受标准输入,并将结果显示在标准输出上,awk支持输入输出重定向。

jsf,通过未指定输入文件,可以快速实时测试/pattern/模式的正确性与否,

例如如下语句:

$ awk  -F"\n"  '$1  ~  /^d.*:$/  {print "ok"}'

#其中的 ~ 符号,表示输入的整行 $1 /pattern/ 匹配,若成功,则打印ok

猜你喜欢

转载自blog.csdn.net/sf_jiang/article/details/78875671
awk
今日推荐