linux中awk进行日志文本的处理过滤

    对于awk命令的介绍可查看linux命令大全http://man.linuxde.net/awk

    linux下日志分析很常见也很重要,看见那一片如汪洋般的日志,想死的心都有了,过滤出关键日志,查看重要信息,定位分析问题也是必须要掌握的一门技能;

    因此coding的时候对日志格式的设计规范很重要,直接决定了bug的定位速度,一般日志过滤处理主要有以下几种方式:

    1.查找关键日志grep
    2.精简日志内容 sed
    3.对记录进行排序sort
    4.统计日志相关记录数 awk

    这里我介绍下awk这种linux中的文本处理技术。

    awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入(stdin)、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势。

    awk命令格式和选项 语法形式 

    awk [options] 'script' var=value file(s) 

    awk [options] -f scriptfile var=value file(s) 

    常用命令选项 

    -F fs   fs指定输入分隔符,fs可以是字符串或正则表达式,如-F: 

    -v var=value   赋值一个用户定义变量,将外部变量传递给awk 

    -f scripfile  从脚本文件中读取awk命令

    -m[fr] val   对val值设置内在限制,-mf选项限制分配给val的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。
    awk的工作原理 

    awk 'BEGIN{ commands } pattern{ commands } END{ commands }'

     第一步:执行BEGIN{ commands }语句块中的语句; 

     第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ commands }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部     被读取完毕。

     第三步:当读至输入流末尾时,执行END{ commands }语句块。

     BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中。 

    END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块。 

    pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。

     

    awk简单使用:

 [plain]  view plain copy
  1. awk [-v 变量名=变量值] [-Fre] [--] '模式 { 语句 }' 变量名=变量值 文件名  
  2. awk [-v 变量名=变量值] [-Fre] -f 脚本文件 [--] 变量名=变量值 文件名  

和sed一样,awk也支持2中方式调用,一种是把awk脚本直接在命令行写入,第二种是把awk写在文件中在命令行中调用。

awk处理方式也与sed类似,对文件中的每一个输入行进行处理,每个处理首先判断是否是模式中匹配的行,是的话就具体执行相应的语句。

不同的是,awk侧重与对每一行的列进行处理,并且,awk脚本和c语言类似也拥有变量,条件判断,循环等复杂语句,所以这里只能简单介绍一下基本应用,详细的请查看后面给出的相关链接。

而且,awk在处理所有行前和处理完行后各有BEGIN和END语句做预处理和后置处理。

例1:打印日志中的第2,3列

[plain]  view plain copy
  1. awk 'BEGIN{FS="@"} {print $2,$3}' demo.log_after_sort   #BEGIN中预处理的是,把@号作为行的列分割符,把分割后的行的第2,3列输出  
输出:(对于从sort得出的结果作为输入)
10117 INFO
10117 INFO
10117 ERROR
10117 ERROR
10117 ERROR
10222 INFO
...略

例2. 统计日志中INFO,ERROR出现的总数,以及总记录数

[plain]  view plain copy
  1. #下面的例子是作为命令行输入的,利用单引号作为换行标记,这样就不用另外把脚本写进文件调用了  
  2. awk '  
  3. BEGIN {  
  4.   FS="@"  
  5. }  
  6.   
  7. {  
  8.   if ($3 == "INFO") {info_count++}  
  9.   if ($3 == "ERROR") {error_count++}  
  10.   
  11. }  
  12.   
  13. END {  
  14.   print "order total count:"NR           #NR是awk内置变量,是遍历的当前行号,到了END区域自然行号就等于总数了  
  15.   printf("INFO count:%d ERROR count:%d\n",info_count,error_count)  
  16. } ' demo.log_after_sort  

输出:

order total count:22
INFO count:5 ERROR count:17

例3. 对指定时间范围内的日志进行统计,包括输出INFO,ERROR总数,记录总数,每个订单记录分类统计

下面的例子综合了前面sed和sort

[plain]  view plain copy
  1. sed -f demo.sed demolog.log | sort -t@ -k2,2n -k3,3r -k1,1 | awk -f demo.awk  

[plain]  view plain copy
  1. #demo.awk  
  2. BEGIN {  
  3.   FS="@"  
  4.   stime="2011-08-23 19:57:31"  
  5.   etime="2011-08-23 19:57:37"  
  6. }  
  7.   
  8. $1 > stime && $1 < etime {  
  9.   if ($3 == "INFO") {info_count++}  
  10.   if ($3 == "ERROR") {error_count++}  
  11.   
  12.   ++total  
  13.   
  14.   status[$2]=status[$2]"\t"$1"\t"$3"\t"$4"\n"  
  15.   
  16. }  
  17.   
  18. END {  
  19.   for(i in status){  
  20.       printf("id:%s:\n%s\n",i,status[i])  
  21.   }  
  22.   
  23.   print "order total count:"total  
  24.   printf("INFO count:%d ERROR count:%d\n",info_count,error_count)  
  25. } <span style="font-size:18px;"><strong>  
  26. </strong></span>  
输出:

id:10117:

2011-08-23 19:57:32 INFO  status:attr_ids成功保存为0|100104|0|100105|100107
2011-08-23 19:57:32 ERROR  status:添加属性id,但由于认证分类参数有误默认取匹配属性名称的第一个属性id:100107

id:10226:

2011-08-23 19:57:32 INFO  status:attr_ids不含0跳过
2011-08-23 19:57:32 ERROR  status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100104
2011-08-23 19:57:33 ERROR  status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100107
2011-08-23 19:57:33 ERROR  status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:46
2011-08-23 19:57:34 ERROR  status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100106
2011-08-23 19:57:35 ERROR  status:添加属性id,但由于没有属性在该分类下默认取匹配属性名称的第一个属性id:100105


#这个例子只是举例说明awk的统计用法,实际运用中可能会统计超时的次数,页面访问次数等。

其他实践时例子:

1. 在本地分支把代码修改从一个分支复制到另一个分支(例子的b1022st.txt是一个记录了文件新增或修改的变化的文件路径名

[plain]  view plain copy
  1. awk 'BEGIN{FS="b1022-scm/"} {system("cp -rf b1022-scm/"$2" b1022-lpscm/"$2);}' /home/nizen/b1022st.txt  
通过awk和其system命令结合,这样就把文件从b1022-scm复制到b1022-lpscm下


2.内置函数 http://www.cnblogs.com/chengmo/archive/2010/10/08/1845913.html
3.内建变量 http://www.linuxsong.org/2010/09/awk-built-in-variable/
4.shell变量传递 http://www.51testing.com/?uid-225738-action-viewspace-itemid-246383
5.awk统计某个开始-结束范围内的关键字累加总数:

[java]  view plain copy
  1. BEGIN {  
  2.   running=0  
  3.   count=0  
  4.   startRow="begin =====>" id            #id,nextId是通过-v 参数从外部传入  
  5.   endRow="begin =====>" nextId  
  6. }  
  7.   
  8. $0 ~ startRow{    # ~是匹配运算符,判断$0是否满足startRow正则表达式  
  9.   running = 1  
  10. #  printf("start\n")  
  11. }  
  12.   
  13. $0 ~ endRow {  
  14.   running = 0  
  15. #  printf("end\n")  
  16. }  
  17.   
  18. {  
  19.   if(running==1) {      # 仅在startRow 和 endRow 范围内统计  
  20.     if($0 ~ "it show") {  
  21. #        printf($0 "\n")  
  22.         str=$0  
  23.         sub(/^.*show times:/, "", str)  
  24.         sub(/ .*$/, "", str)  
  25.         printf(str "\n")  
  26.         count = count + str  
  27.     }  
  28.   }  
  29. }  
  30.   
  31. END {  
  32.   printf("showTimeCount:"+count)  
  33. }  
6. printf "10ms occur:%.2lf%%\n",t10/total*100 #输出百分比数据,精确到百分位后2位

    以上awk的简单使用摘录自http://blog.csdn.net/ultrani/article/details/6750434

自己试验的一部分:
   通过shell语言编写自动过滤脚本,过滤当天的日志:
  1、 实时读取本地时间
   
  2、二维数组记录可用日志和二维数组记录链接变动日志,END中根据两个数组进行输出筛选和统计
   
  3、颜色输出文本日志区分不同类别的日志
    
    仅实验以上6种颜色,可自行修改下条语句中的标红数字,上图从上到下分别对应颜色33~37
     print "\033[40;33m"redConf[i][0]"\t\033[0m"

   
   



    




    


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值