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.待续

  • 相关阅读:
    windows操作系统的电脑越用越卡?简说几种原因和解决方法。
    不懂电脑也能自己重装系统,可视化傻瓜式一键重装系统不求人!!!
    023.Ubuntu常见个性化配置
    Blazor带我重玩前端(六)
    Blazor带我重玩前端(五)
    WSL2 配置及ubuntu18.04安装mysql8.0+
    用ThreadLocal来优化下代码吧
    基于canal的client-adapter数据同步必读指南
    「从零单排canal 07」 parser模块源码解析
    实用向—总结一些唯一ID生成方式
  • 原文地址:https://www.cnblogs.com/ungshow/p/2197936.html
Copyright © 2011-2022 走看看