zoukankan      html  css  js  c++  java
  • awk 小结

    原文: http://blog.romebuilder.com/2011/10/521/

    1.处理时间

    日志中的时间格式多为 2011-09-30 00:00:00,035 ,有时,我需要对日志中给定的时间段进行数据分析,这时就要对每条日志记录的时间做对比。但是如何来高效地比较时间呢?

    我的想法是,将时间字条窜转化为unix timestamp,在Awk中实现这种转换有两种方式,一种是调用shell命令,date;另一种是使用内置的mktime.

    下面是调用shell 命令 date

    egrep -i "<—.*login" connector.log | awk -F ' ' '
    BEGIN{
        restartTimeStr = "2011-09-21 09:43:28,367"
        "date +%s -d ""\""restartTimeStr"\""|getline restartTimestamp
        printf("Server restarted at %s, timestamp is %s\n", restartTimeStr, restartTimestamp)
        before = "before"
        after = "after"
    }
    {
        split($0, rowArr); dateStr = $1" "$2;
        "date +%s -d ""\""dateStr"\""|getline timestamp;
       
        if(timestamp < restartTimestamp) addrMap[$7][before]++;
        else if(timestamp > restartTimestamp) addrMap[$7][after]++;
    }
    END{
        for(addr in addrMap) printf "Address: %s , before: %s , after : %s\n", addr,addrMap[addr][before], addrMap[addr][after]
    }'

    这种做法存在的问题是,当你的日志文件非常大时,如10G+时,这段就可能出问题。系统可能会提示里,文件句柄用完。因为在调用shell命令时,awk可能会新开一个管道用于与shell通信。

    那么,下面来说说使用mktime(注:这个内置函数好像只在gawk里面,对于awk的多种版本,我还不太了解).

    egrep -i "<—.*login" connector.log | awk -F ' ' '
    BEGIN{
        restartTimeStr = "2011-09-21 09:43:28,367"
        "date +%s -d ""\""restartTimeStr"\""|getline restartTimestamp
        printf("Server restarted at %s, timestamp is %s\n", restartTimeStr, restartTimestamp)
        before = "before"
        after = "after"
    }
    {
        split($0, rowArr); dateStr = $1" "$2; /* dateStr format like:  2011-09-30 10:15:17,333*/
       
        /*split the date str*/
        split(dateStr, dateStrArr, "[\\- :]");
        dateStr = ""
        for(i=1;i<=length(dateStrArr);i++) dateStr = dateStr" "dateStrArr[i]
        /* now date str format like: 2011 09 30 10 15 17,333*/
        timestamp = mktime(dateStr)

       
        if(timestamp < restartTimestamp) addrMap[$7][before]++;
        else if(timestamp > restartTimestamp) addrMap[$7][after]++;
    }
    END{
        for(addr in addrMap) printf "Address: %s , before: %s , after : %s\n", addr,addrMap[addr][before], addrMap[addr][after]
    }'

    mktime 让人不爽的地方时,它只接受(YY MM DD HH mm SS)这样的参数格式,用户好像无法指定传入的参数格式。因此,在调用这个函数之前,我们必需将日期先进行解析。另外,要注意的一点是,在使用awk的 for语句时,for(var in array)好像是乱序输出结果,那么对于这个顺序敏感的——如这个日期的顺序——就需要按索引来读取了。

    虽然mktime用起来比较难看,但是,就上面两段代码而言,后者的速度要比前者快上好几倍。

    2.排序

    awk的内置的排序函数,但还没有搞清楚怎么用才合适,因些,我就将结果输出后,用shell的sort命令来排序。在我遇到的情况中,一般都不需要在代码的处理过程中使用排序,而是在得到处理结果后排序,所以使用shell sort也比较合适。

    egrep -i "<—.*login" connector.log | awk -F '[' '{addr = substr($5, 0, index($5, "->") - 1); addrMap[addr]++} END{ for(addr in addrMap) printf "%s %s\n", addr,addrMap[addr]}' | sort -k2 -n -r | head -20

    3.待续

  • 相关阅读:
    【2017-03-09】SQL Server 数据库基础、四种约束
    【2017-03-05】函数基础、函数四种结构、ref和out参数、递归
    procecss on技巧
    角度与弧度
    C语言求π的方法
    三轴加速度传感器角度值转换原理
    C获取数组长度
    如何使用ProcessOn制作思维导图
    processon完全装逼指南
    NORDIC GATT事件
  • 原文地址:https://www.cnblogs.com/ungshow/p/2197936.html
Copyright © 2011-2022 走看看