awk脚本学习小结

  awk是Linux/Unix系统中的shell过滤工具,它也是一种自解释的编程语言。
  使用awk对某个文件执行一些简单操作,可以直接使用awk '' file 的命令格式操作文件file。
  若是进行一些较复杂的理,语句会很长,不易维护。这时,我们可以使用awk脚本来维护。

  awk脚本是一个可执行的文件,我们习惯以.awk来命名它。写好的awk脚本,加上可执行权限来使用,格式:./do.awk file
  它的内部结构可以简要概括为如下4个部分:
  $test.awk
  #! /bin/awk -f
  BEGIN{}
  {}
  END{}

  第一行告知脚本系统中awk的位置。
  第二行是脚本主体之前,执行些什么。该行内的语句,可以只执行一次(这句话的意思,会在后文中举例说明)。
  第三行是脚本主体。此中的语句,会根据awk要处理的对象文本中的行数,以及匹配条件,执行零次或多次。
  第四行是脚本主体之后,执行些什么。(该部分与BEGIN类似,只是相对于主体的位置不同)。

  下面以处理grade.txt文件(来自shell编程教材)为例,说明awk脚本的使用方法(awk基本语法和函数,这里不做说明)。
  grade.txt文件内容为柔道学员比赛信息(姓名 升段日期 学员编号 腰带级别 年龄 目前积分 比赛最高分):
  M.Tansley  05/99   48311  Green   8   40   44
  J.Lulu     06/99   48317  Green   9   24   26
  P.Bunny    02/99   48     Yellow  12  35   28
  J.Troll    07/99   4842   Brown-3 12  26   26
  L.Tansley  05/99   4748   Brown-2 12  30   28
 
  现在,我们想列出学员姓名和目前积分。这个要求实现起来很容易,一条awk语句即可:awk '{print $1,$6}' grade.txt
  效果如下:
  M.Tansley 40
  J.Lulu 24
  P.Bunny 35
  J.Troll 26
  L.Tansley 30
 
  但是这个效果可能对于挑剔的我们来说,不尽人意:列与列对齐的很差,没有列名,等等。
  好的,现在我们在原要求基础上,再加三个要求:
  1. 要有列名Name和Score;
  2. 要在结尾显示这几个学员的总分和平均分;
  3. 要求列与列对齐。
  咱们先给出最终要求的效果,如下:
  Name       Score
  ================
  M.Tansley  40
  J.Lulu     24
  P.Bunny    35
  J.Troll    26
  L.Tansley  30
  The total is 155
  The average is 31

  这样看起来是不是更美观、合理?这样的实现,虽然也可以一条awk语句搞定,但是那样的语句很长,不利于维护。所以我们使用脚本来维护。
  由于是初学,我的第一个awk脚本是这样写的(stu.awk):
  #! /bin/awk -f
  {
  printf"%-10s %5s\n================\n","Name","Score";
  (tot+=$6);
  printf "%-10s %2d\n",$1,$6;
  print "The total is "tot;print "The average is "tot/NR
  }
  然而增加可执行权限,执行./stu.awk grade.txt 后的效果却是:
  Name       Score
  ================
  M.Tansley  40
  The total is 40
  The average is 40
  Name       Score
  ================
  J.Lulu     24
  The total is 64
  The average is 32
  Name       Score
  ================
  P.Bunny    35
  The total is 99
  The average is 33
  Name       Score
  ================
  J.Troll    26
  The total is 125
  The average is 31.25
  Name       Score
  ================
  L.Tansley  30
  The total is 155
  The average is 31

  这里可见,主体部分的语句,会根据文本匹配行数,执行多次。于是又修改了一下,将Name和Score放到BEGIN中:
  我的第二个awk脚本是这样写的(stu.awk):
  #! /bin/awk -f
  BEGIN{
  printf"%-10s %5s\n================\n","Name","Score"
  }
  {
  (tot+=$6);
  printf "%-10s %2d\n",$1,$6;
  print "The total is "tot;print "The average is "tot/NR
  }
 
  执行./stu.awk grade.txt的效果:
  Name       Score
  ================
  M.Tansley  40
  The total is 40
  The average is 40
  J.Lulu     24
  The total is 64
  The average is 32
  P.Bunny    35
  The total is 99
  The average is 33
  J.Troll    26
  The total is 125
  The average is 31.25
  L.Tansley  30
  The total is 155
  The average is 31

  这次大有改观,Name和Score不会重复出现了。接下来就是总分和平均值重复的问题了。
  我的第三个awk脚本是这样写的(stu.awk):
  #! /bin/awk -f
  BEGIN{
  printf"%-10s %5s\n================\n","Name","Score"
  }
  {
  (tot+=$6);
  printf "%-10s %2d\n",$1,$6;
  }
  END{
  print "The total is "tot;print "The average is "tot/NR
  }

  这次,终于出现了预期的结果:
  Name       Score
  ================
  M.Tansley  40
  J.Lulu     24
  P.Bunny    35
  J.Troll    26
  L.Tansley  30
  The total is 155
  The average is 31

  理论上的东西,咱也不多说了,相信通过这三个脚本修改过程,我们应该可以感性的认识到awk脚本中,BEGIN和END的作用了。希望这个例子,可以对初学awk脚本的XDJM们,有所帮助。
  愿大家工作愉快!
 
  PS:其实 ./stu.awk grade.txt等同于awk 'BEGIN{...}{...}END{...}' grade.txt(请将对应块中的语句补齐即可,比较长,这也是用awk脚本的原因)这条语句的效果,大家不妨试试看。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值