【问题标题】:analyzing time tracking data in linux在linux中分析时间跟踪数据
【发布时间】:2015-07-01 07:10:14
【问题描述】:

我有一个包含一系列事件的日志文件。现在,我想分析数据以计算不同时间间隔的事件数。每个条目都显示在此时间戳中发生了一个事件。例如这里是日志文件的一部分

09:00:00
09:00:35
09:01:20
09:02:51
09:03:04
09:05:12
09:06:08
09:06:46
09:07:42
09:08:55

我需要每隔 5 分钟计算一次事件。结果应该是这样的:

09:00  4       //which means 4 events from time 09:00:00 until 09:04:59<br>
09:05  5        //which means 4 events from time 09:00:05 until 09:09:59<br>

等等。

你知道 bash、shell、awk 中的任何技巧吗?
任何帮助表示赞赏。

【问题讨论】:

标签: linux bash shell awk


【解决方案1】:

awk 来救援。

awk -v FS="" '{min=$5<5?0:5; a[$1$2$4min]++} END{for (i in a) print i, a[i]}' file

说明

它获取每行中第 1、2、4 和 5 个字符的值,并跟踪它们出现了多少次。要在0-45-9 范围内进行分组,它会创建变量min,即在第一种情况下为0,在第二种情况下为5

样本

根据您的意见,

$ awk -v FS="" '{min=$5<5?0:5; a[$1$2$4min]++} END{for (i in a) print i, a[i]}' a
0900 5
0905 5

使用另一个样本输入,

$ cat a
09:00:00
09:00:35
09:01:20
09:02:51
09:03:04
09:05:12
09:06:08
09:06:46
09:07:42
09:08:55
09:18:55
09:19:55
10:09:55
10:19:55

$ awk -v FS="" '{min=$5<5?0:5; a[$1$2$4min]++} END{for (i in a) print i, a[i]}' a
0900 5
0905 5
0915 2
1005 1
1015 1

【讨论】:

  • 如果时间间隔是 10 分钟,这将是一个完美的解决方案。但是对于 5 分钟的间隔,它似乎需要更复杂的 awk 命令。
【解决方案2】:

awk 的另一种方式

awk -F : '{t=sprintf ("%02d",int($2/5)*5);a[$1 FS t]++}END{for (i in a) print i,a[i]}' file |sort -t: -k1n -k2n

09:00 5
09:05 5

解释:

use : as field seperator
int($2/5)*5 is used to group the minutes into every 5 minute (00,05,10,15...)
a[$1 FS t]++ count the numbers.
the last sort command will output the sorted time.

【讨论】:

    【解决方案3】:

    通过uniq 输出的 Perl 只是为了好玩:

    $ cat file
    09:00:00
    09:00:35
    09:01:20
    09:02:51
    09:03:04
    09:05:12
    09:06:08
    09:06:46
    09:07:42
    09:08:55
    09:18:55
    09:19:55
    10:09:55
    10:19:55
    11:21:00
    

    命令:

    perl -F: -lane 'print $F[0].sprintf(":%02d",int($F[1]/5)*5);' file | uniq -c
    

    输出:

       5 09:00
       5 09:05
       2 09:15
       1 10:05
       1 10:15
       1 11:20
       1 11:00
    

    或者只是 perl:

    perl -F: -lane '$t=$F[0].sprintf(":%02d",int($F[1]/5)*5); $c{$t}++; END { print join(" ", $_, $c{$_}) for sort keys %c }' file
    

    输出:

    09:00 5
    09:05 5
    09:15 2
    10:05 1
    10:15 1
    11:00 1
    11:20 1
    

    【讨论】:

      【解决方案4】:

      我意识到这是一个老问题,但当我偶然发现它时,我忍不住从另一个方向戳它......

      sed -e 's/:/ /' -e 's/[0-4]:.*$/0/' -e 's/[5-9]:.*$/5/' | uniq -c
      

      在这种形式中,它假定数据来自标准输入,或者在管道之前添加文件名作为最后一个参数。

      这与 Michal 最初的方法没有什么不同,但如果您碰巧需要对庞大的日志进行快速而肮脏的分析,sed 是一个轻量级且功能强大的工具。

      假设数据确实是常规格式 - 结果中会出现任何问题。

      作为细分 - 给定输入

      09:00:35
      09:01:20
      09:02:51
      09:03:04
      09:05:12
      09:06:08
      

      并单独应用每个编辑子句,中间结果如下: 1) 去掉第一个冒号。

      -e 's/:/ /'
      09 00:35
      09 01:20
      09 02:51
      09 03:04
      09 05:12
      

      2) 将分钟 0 到 4 转换为 0。

      -e 's/[0-4]:.*$/0/'
      09 00
      09 00
      09 00
      09 00
      09 05:12
      09 06:08
      

      3) 将 5-9 分钟转换为 5 分钟:

      -e 's/[5-9]:.*$/5/'
      09 00
      09 00
      09 00
      09 00
      09 05
      09 05
      

      2 和 3 还会从行中删除所有尾随内容,这会使行不唯一(因此 'uniq -c' 将无法产生所需的结果)。

      也许使用 sed 作为前端的最大优势在于您可以选择感兴趣的行,例如,如果 root 远程登录:

      sed -e '/sshd.*: Accepted .* for root from/!d' -e 's/:/ /' ... /var/log/secure
      

      【讨论】:

        猜你喜欢
        • 2011-11-10
        • 1970-01-01
        • 1970-01-01
        • 2022-01-06
        • 2012-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多