bash组时间和平均值+总和列

时间:2016-05-27 11:34:43

标签: time awk grouping ksh gawk

我在Linux系统上有如下所示的每日文件输出,并且想知道是否有一种方法可以使用awk /通过shell脚本以30分钟为基础增加$ 7和avg $ 3以及$ 4 $ 5 $ 6 $ 7 $ 8分组数据gawk或类似的东西?

04:04:13 04:10:13 2.13 36 27 18 18 0
04:09:13 04:15:13 2.37 47 38 13 34 0
04:14:13 04:20:13 2.19 57 37 23 33 1
04:19:13 04:25:13 2.43 43 35 13 30 0
04:24:13 04:30:13 2.29 48 40 19 28 1
04:29:13 04:35:13 2.33 56 42 16 40 0
04:34:13 04:40:13 2.21 62 47 30 32 0
04:39:13 04:45:13 2.25 44 41 19 25 0
04:44:13 04:50:13 2.20 65 50 32 33 0
04:49:13 04:55:13 2.47 52 38 16 36 0
04:54:13 05:00:13 2.07 72 54 40 32 0
04:59:13 05:05:13 2.35 53 41 19 34 0

所以基本上这小时的数据会产生这样的结果:

04:04:13-04:29:13 2.29 287 219 102 183 2 
04:34:13-04:59:13 2.25 348 271 156 192 0

这是我到目前为止使用awk在时间帧之间进行搜索但我认为有一种更容易的方法来完成分组而不会每隔30分钟唤醒

awk '$1>=from&&$1<=to' from="04:00:00" to="04:30:00" | awk '{ total += $3; count++ } END { print total/count }'|awk '{printf "%0.2f\n", $1'}

awk '$1>=from&&$1<=to' from="04:00:00" to="04:30:00" | awk '{ sum+=$4} END {print sum}'

2 个答案:

答案 0 :(得分:0)

这应该做你想要的:

{
    split($1, times, ":");
    i = (2 * times[1]);
    if (times[2] >= 30) i++;
    if (!start[i] || $1 < start[i]) start[i] = $1;
    if (!end[i] || $1 > end[i]) end[i] = $1;
    count[i]++;
    for (col = 3; col <= 8; col++) {
        data[i, col] += $col;
    }
}

END {
    for (i = 1; i <= 48; i++) {
        if (start[i]) {
            data[i, 3] = data[i, 3] / count[i];
            printf("%s-%s %.2f", start[i], end[i], data[i, 3]);
            for (col = 4; col <= 8; col++) {
                printf(" " data[i, col]);
            }
            print "";
        }
    }
}

如您所见,我将这一天划分为48个半小时的间隔,并根据第一列中的时间将数据放入其中一个箱中。输入用尽后,我打印出所有非空的箱子。

答案 1 :(得分:0)

就个人而言,我会用Python或Perl来做这件事。在awk中,数组没有被排序(好吧,你可以使用assorti对数组进行排序......)这使得打印有序的存储桶更有用。

以下是大纲:

  1. 阅读输入
  2. 将时间戳转换为秒
  3. 在所需时间范围的存储桶中添加数据元素的有序(或可排序)关联数组(或者,只保持运行总计)。
  4. 读取数据后,按您的意愿处理。
  5. 以下是Python版本:

    #!/usr/bin/python
    
    from collections import OrderedDict
    import fileinput
    times=[]
    interval=30*60
    od=OrderedDict()
    
    for line in fileinput.input():
        li=line.split()
        secs=sum(x*y for x,y in zip([3600,60,1], map(int, li[0].split(":"))))
        times.append([secs, [li[0], float(li[2])]+map(int, li[3:])])
    
    current=times[0][0]
    for t, li in times:
        if t-current<interval:
            od.setdefault(current, []).append(li)
        else:
            current=t
            od.setdefault(current, []).append(li)
    
    for s, LoL in od.items():
        avg=sum(e[1] for e in LoL)/len(LoL)
        sums=[sum(e[i] for e in LoL) for i in range(2,7)]
        print "{}-{} {:.3} {}".format(LoL[0][0], LoL[-1][0], avg, ' '.join(map(str, sums))) 
    

    在示例数据上运行它:

    $ ./ts.py ts.txt
    04:04:13-04:29:13 2.29 287 219 102 183 2
    04:34:13-04:59:13 2.26 348 271 156 192 0    
    

    优点是您可以轻松更改间隔,类似的技术可以使用超过天的时间戳。

    如果你真的想要awk,你可以这样做:

    awk 'BEGIN{ interval=30*60 }
       function fmt(){
              line=sprintf("%s-%s %.2f %i %i %i %i %i", ls, $1, sums[3]/count, 
                                 sums[4], sums[5], sums[6], sums[7], sums[8])
       }
       {
           split($1,a,":") 
           secs=a[1]*3600+a[2]*60+a[3]
           if (NR==1) { 
                low=secs
                ls=$1
                count=0
                for (i=3; i<=8; i++)
                   sums[i]=0
            }                       
            for (i=3; i<=8; i++){
               sums[i]+=$i
            }
            count++         
            if (secs-low<interval) {
                fmt()
                }       
            else {
                print line
                low=secs
                ls=$1
                count=1
                for (i=3; i<=8; i++)
                   sums[i]=$i                           
                }                   
       }
       END{
            fmt()
            print line
       }' file
    04:04:13-04:29:13 2.29 287 219 102 183 2
    04:34:13-04:59:13 2.26 348 271 156 192 0