无线&移动互联网技术研发

换位思考·····
posts - 19, comments - 53, trackbacks - 0, articles - 283
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

awk使用

Posted on 2009-11-29 11:53 Gavin.lee 阅读(266) 评论(0)  编辑  收藏 所属分类: Linux command

 


调用awk有三种方式调用awk,第一种是命令行方式,如:
Shell代码
  1. awk [-F field-separator] 'commands' input-file(s)  

这里,commands是真正的awk命令。上面例子中,-F域分隔符]是可选的,因为a w k使用空格作为缺省的域分隔符,因此如果要浏览域间有空格的文本,不必指定这个选项,但如果要浏览诸如 passwd文件,此文件各域以冒号作为分隔符,则必须指明- F选项:
Shell代码
  1. awk -F: 'commands' input-file  
第二种方法是将所有a w k命令插入一个文件,并使 a w k程序可执行,然后用a w k命令解释器作为脚本的首行,以便通过键入脚本名称来调用它。
第三种方式是将所有的awk命令插入一个单独文件,然后调用:
Shell代码
  1. awk -f awk_script_ file input_file(s)  
- f选项指明在文件awk_script_ file中的a w k脚本,input_file(s)是使用awk进行浏览的文件名。

模式和动作
任何awk语句都由模式和动作组成。在一个awk脚本中可能有许多语句。模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。如果省略模式部分,动作将时刻保持执行状态。模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段BEGIN和END。使用BEGIN语句设置计数和打印头。BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文件开始执行。 END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态标志。如果不特别指明模式, awk总是匹配或打印行数。实际动作在大括号{ }内指明。动作大多数用来打印,但是还有些更长的代码诸如 if和循环(looping)语句及循环退出结构。如果不指明采取动作, awk将打印出所有浏览出来的记录。

域和记录
awk执行时,其浏览域标记为$1,$2 . . . $n。这种方法称为域标识。使用这些域标识将更容易对域进行进一步处理。使用$1,$3表示参照第1和第3域,注意这里用逗号做域分隔。如果希望打印一个有5个域的记录的所有域,不必指明 $1,$2,$3,$4 ,$5,可使用$0,意即所有域。awk浏览时,到达一新行,即假定到达包含域的记录末尾,然后执行新记录下一行的读动作,并重新设置域分隔。注意执行时不要混淆符号$和shell提示符$,它们是不同的。

打印所有域的信息
Shell代码
  1. /home/l/g/tomotoboy >who   
  2. liuzk423   pts/6        Jul 20 08:27    (219.245.104.240)   
  3. tomotoboy   pts/16       Aug  7 23:33   (219.221.98.71)   
  4. liuqingaihn   pts/21       Aug  7 23:10 (116.29.229.116)   
  5. guise      pts/35       Aug  7 21:13    (58.41.162.27)   
  6. uyty       pts/38       Aug  7 22:09    (p3213-ipbf803souka.saitama.ocn.ne.jp)   
  7. yagamil    pts/46       Aug  7 20:48    (199.40.206.191)   
  8. /home/l/g/tomotoboy >who | awk '{print $0}'  
  9. liuzk423   pts/6        Jul 20 08:27    (219.245.104.240)   
  10. tomotoboy   pts/16       Aug  7 23:33   (219.221.98.71)   
  11. liuqingaihn   pts/21       Aug  7 23:10 (116.29.229.116)   
  12. guise      pts/35       Aug  7 21:13    (58.41.162.27)   
  13. uyty       pts/38       Aug  7 22:09    (p3213-ipbf803souka.saitama.ocn.ne.jp)   
  14. yagamil    pts/46       Aug  7 20:48    (199.40.206.191)  


抽取第一域,并打印出来:
Shell代码
  1. /home/l/g/tomotoboy >who|awk '{print $1}'  
  2. liuzk423   
  3. tomotoboy   
  4. liuqingaihn   
  5. guise   
  6. uyty   
  7. yagamil  


打印第一域、第三域
Shell代码
  1. /home/l/g/tomotoboy >who | awk '{print $1"\t"$3}'  
  2. liuzk423        Jul   
  3. tomotoboy       Aug   
  4. liuqingaihn     Aug   
  5. guise           Aug   
  6. uyty            Aug   
  7. yagamil         Aug  


打印信息头和信息尾
Shell代码
  1. /home/l/g/tomotoboy >who | awk  'BEGIN {print "--------BEGIN-------\n"} {print $1"\t"$3} END {print "----------END-------"}'  
  2. --------BEGIN-------   
  3.   
  4. liuzk423        Jul   
  5. tomotoboy       Aug   
  6. liuqingaihn     Aug   
  7. guise   Aug   
  8. uyty    Aug   
  9. kenhq   Aug   
  10. yagamil Aug   
  11. ----------END-------  


如果第一个域等于tomotoboy
Shell代码
  1. /home/l/g/tomotoboy >who | awk  '{if ($1~/tomotoboy/) print $0}'  
  2. tomotoboy   pts/16       Aug  7 23:33   (219.221.98.71)  


如果行的域中包含tomotoboy就打印它
Shell代码
  1. /home/l/g/tomotoboy >who | awk  '$0 ~/tomotoboy/'  
  2. tomotoboy   pts/16       Aug  7 23:33   (219.221.98.71)  


不匹配
Shell代码
  1. /home/l/g/tomotoboy >who | awk  '{if ($1!~/tomotoboy/) print $0}'  
  2. liuzk423   pts/6        Jul 20 08:27    (219.245.104.240)   
  3. uyty       pts/38       Aug  7 22:09    (p3213-ipbf803souka.saitama.ocn.ne.jp)   
  4. kenhq      pts/40       Aug  7 23:46    (116.77.50.7)   
  5. yagamil    pts/46       Aug  7 20:48    (199.40.206.191)   
  6.   
  7. /home/l/g/tomotoboy >who | awk  '$0  !~/tomotoboy/'  
  8. liuzk423   pts/6        Jul 20 08:27    (219.245.104.240)   
  9. liuqingaihn   pts/21       Aug  7 23:54 (116.29.229.116)   
  10. uyty       pts/38       Aug  7 22:09    (p3213-ipbf803souka.saitama.ocn.ne.jp)   
  11. kenhq      pts/40       Aug  7 23:46    (116.77.50.7)   
  12. yagamil    pts/46       Aug  7 20:48    (199.40.206.191)  


行首
打印行首包含to的行
Shell代码
  1. /home/l/g/tomotoboy >who | awk  '/^to/'  
  2. tomotoboy   pts/16       Aug  7 23:33   (219.221.98.71)  

AND
打印第一域为tomotoboy,第三域为Aug的行
Shell代码
  1. /home/l/g/tomotoboy >who | awk  '{if ($1=/tomotoboy/ && $2=/Aug/) print $0}'  
  2. awk: syntax error near line 1  
  3. awk: illegal statement near line 1  
  4. /home/l/g/tomotoboy >who | awk  '{if ($1~/tomotoboy/ && $3~/Aug/) print $0}'  
  5. tomotoboy   pts/16       Aug  7 23:33   (219.221.98.71)  

注意区分“=”与“==”,获得两种截然不同的结果
Shell代码
  1. /home/l/g/tomotoboy >who | awk  '{if ($1="tomotoboy" && $3="Aug") print $0}'  
  2. tomotoboy pts/6 Aug 20 08:27 (219.245.104.240)   
  3. tomotoboy pts/16 Aug 7 23:33 (219.221.98.71)   
  4. tomotoboy pts/21 Aug 8 00:05 (116.29.229.116)   
  5. tomotoboy pts/35 Aug 8 00:05 (116.29.229.116)   
  6. tomotoboy pts/38 Aug 7 22:09 (p3213-ipbf803souka.saitama.ocn.ne.jp)   
  7. tomotoboy pts/40 Aug 7 23:46 (116.77.50.7)   
  8. tomotoboy pts/46 Aug 7 20:48 (199.40.206.191)  


Shell代码
  1. /home/l/g/tomotoboy >who | awk  '{if ($1=="tomotoboy" && $3=="Aug") print $0}'  
  2. tomotoboy   pts/16       Aug  7 23:33   (219.221.98.71)  


awk内置变量
Shell代码
  1. /home/l/g/tomotoboy >who|awk '{print NF,NR,$0}'  
  2. 6 1 liuzk423   pts/6        Jul 20 08:27        (219.245.104.240)   
  3. 6 2 tomotoboy   pts/16       Aug  7 23:33       (219.221.98.71)   
  4. 6 3 liuqingaihn   pts/21       Aug  8 00:05     (116.29.229.116)   
  5. 6 4 liuqingaihn   pts/35       Aug  8 00:05     (116.29.229.116)   
  6. 6 5 uyty       pts/38       Aug  7 22:09        (p3213-ipbf803souka.saitama.ocn.ne.jp)   
  7. 6 6 kenhq      pts/40       Aug  7 23:46        (116.77.50.7)   
  8. 6 7 yagamil    pts/46       Aug  7 20:48        (199.40.206.191)  


awk内置字符串函数
awk内置字符串函数,awk又很多字符处理函数,这里以length为例
Shell代码
  1. /home/l/g/tomotoboy >who| awk '{print length($1)" "$1}'  
  2. 8 liuzk423   
  3. 9 tomotoboy   
  4. 11 liuqingaihn   
  5. 11 liuqingaihn   
  6. 5 kenhq   
  7. 7 yagamil  

如果第一域的长度大于7就输出
Shell代码
  1. /home/l/g/tomotoboy >who| awk '{if(length($1)>7) print length($1)" "$1}'  
  2. 8 liuzk423   
  3. 9 tomotoboy   
  4. 11 liuqingaihn   
  5. 11 liuqingaihn  


字符串屏蔽序列
使用字符串或正则表达式时,有时需要在输出中加入一新行或查询一元字符。打印一新行时,(新行为字符\n) ,给出其屏蔽序列,以不失其特殊含义,用法为在字符串前加入反斜线。例如使用\n强迫打印一新行。如果使用正则表达式,查询花括号({ }) ,在字符前加反斜线,如/ \ { /,将在awk中失掉其特殊含义。
Shell代码
  1. \b 退格键      \t tab键   
  2. \f 走纸换页    \ddd 八进制值   
  3. \n 新行        \c 任意其他特殊字符,例如\\为反斜线符号   
  4. \r 回车键   
  5. /home/l/g/tomotoboy >who |awk '{print $1"\t""\t"$2"\n"}'  
  6. liuzk423                pts/6  
  7.   
  8. tomotoboy               pts/16  
  9.   
  10. liuqingaihn             pts/21  
  11.   
  12. liuqingaihn             pts/35  
  13.   
  14. kenhq                   pts/40  
  15.   
  16. yagamil                 pts/46  


printf
printf修饰符,prinf基本域C语言的printf相同下面开始举例
Shell代码
  1. /home/l/g/tomotoboy >echo "65" |awk '{printf "%c\n",$0}'  
  2. A   
  3. /home/l/g/tomotoboy >echo "65" |awk '{printf "%d\n",$0}'  
  4. 65  
  5. /home/l/g/tomotoboy >echo "65" |awk '{printf "%c\t\t%d\n",$0,$0}'  
  6. A               65  


awk数组
Java代码
  1. /home/l/g/tomotoboy >awk 'BEGIN {print split("123#456#789",myarray,"#")}'  
  2. 3  

在上面的例子中,split返回数组myarray下标数。实际上myarray数组为:
myarray[1]=123
myarray[2]=456
myarray[3]=789
数组使用前,不必定义,也不必指定数组元素个数。经常使用循环来访问数组。下面是一种循环类型的基本结构:
For (element in array) print array[element]
对于记录“123#456#789” ,先使用split函数划分它,再使用循环打印各数组元素。操作脚本如下:
Shell代码
  1. #!/bin/awk -f   
  2. #name: arraytest.awk   
  3. #pprint out am array   
  4. BEGIN{   
  5. record="123#456#789";   
  6. split(record,myarray,"#")}   
  7. END { for (i in myarray) {print myarray[i]}}  

要运行脚本,使用/dev/null作为输入文件。
Shell代码
  1. /home/l/g/tomotoboy >arraytest.awk /dev/null   
  2. 456  
  3. 789  
  4. 123  
小结
awk语言学起来可能有些复杂,但使用它来编写一行命令或小脚本并不太难。awk是shell编程的一个重要工具。在shell命令或编程中,虽然可以使用awk强大的文本处理能力,但是并不要求你成为这方面的专家

只有注册用户登录后才能发表评论。


网站导航: