Shell 基于分钟的列总和

Shell 基于分钟的列总和,shell,unix,awk,Shell,Unix,Awk,下面是我的输入文件: 第一列是一天中的小时和分钟的组合 第二列是计数 数据是按分钟计算的 我需要通过对每一个分块进行求和,将数据转换为分块,即[1-5、6-10等等]。我需要这些数据在jfree图表中绘图。请建议如何获得输出 输入: 11.01:5 11.02:4 11.03:3 11.04:8 11.05:2 12.11:3 12.12:4 12.13:1 12.15:0 13.03:04 22.56:01 22.57:03 22.58:2 23.00:0 输出: 11.05:22 12

下面是我的输入文件:

  • 第一列是一天中的小时和分钟的组合
  • 第二列是计数
数据是按分钟计算的

我需要通过对每一个分块进行求和,将数据转换为分块,即[1-5、6-10等等]。我需要这些数据在jfree图表中绘图。请建议如何获得输出

输入:

11.01:5
11.02:4
11.03:3
11.04:8
11.05:2
12.11:3
12.12:4
12.13:1
12.15:0
13.03:04
22.56:01
22.57:03
22.58:2
23.00:0
输出:

11.05:22
12.15:8
13.05:4
23.00:6

这个问题可以用一百万种不同的方法来解决:sed、awk、python等等

下面是使用常用bash命令的方法

#!/bin/bash

# extract the unique set of hours from the input (i.e. 11, 12, 13, 22, 23)
#
hours=$(cut -f 1 -d . test.txt | sort -u)
for hour in $hours; do

    # initialize sum for this hour
    #
    count=0

    # extract the number following the ':'
    #
    for x in $(grep "^$hour" test.txt | cut -f 2 -d :); do
        # sum up the numbers following the ':'
        #
        count=$(($count + $x))
    done

    # Extract the last timestamp for the given hour
    #
    t=$(grep "^$hour" test.txt | tail -1  | cut -f 1 -d :)

    # Print the desired output of timestamp:sum
    #
    echo $t:$count
done
以下是输出:

11.05:22
12.15:8
13.03:4
22.58:6
23.00:0
您的输入存储在文件test.txt中:

11.01:5
11.02:4
11.03:3
11.04:8
11.05:2
12.11:3
12.12:4
12.13:1
12.15:0
13.03:04
22.56:01
22.57:03
22.58:2
23.00:0
让我指出您在脚本中看到的一些命令

  • cut
    用于从输入中提取列
    cut-f1-d。
    将从您的输入中提取小时数<代码>-f 1表示打印列1,而
    -d.
    表示使用“.”作为去污剂
  • tail-f1
    打印tail输入的最后一行
  • sort-u
    从输入中删除重复的行
  • 此awk应在以下情况下工作:

    awk -F '[.:,]' -v OFS=: '{
       p=5*int(($2+4)/5);
       $1=1*$1;
       if(p==60){
          p="0";
          $1++
       }
       k=sprintf("%02d.%02d", $1, p)
    }
    !s[k]{
       b[++n]=k
    }
    {
       s[k]+=$3
    }
    END{
       for (i=1; i<=n; i++)
          print b[i],s[b[i]]
    }' file
    11.05:22
    12.15:8
    13.05:4
    23.00:6
    
    awk-F'[.:,]'-vofs=:'{
    p=5*int($2+4)/5);
    $1=1*$1;
    如果(p==60){
    p=“0”;
    $1++
    }
    k=sprintf(“%02d.%02d”,$1,p)
    }
    !s[k]{
    b[++n]=k
    }
    {
    s[k]+=$3
    }
    结束{
    
    对于(i=1;i这是一份草案。一旦您展示了一些尝试,我将提供一种更通用的方法:

    awk -F"[.:]" -v OFS=":" '{r=sprintf("%d", ($2-1)/5); r=(r+1)*5; a[$1"."r]+=$3} END {for (i in a) print i, a[i]}' file
    
    对于给定的输入,它将返回:

    22.60:6
    13.5:4
    12.15:8
    23.5:0
    11.5:22
    
    关键是把每一个1,2,3,4和5映射到5。我这样说:

    d -> d-1 -> (d-1)/5 (int division) -> (d-1)/5 * 5
    

    要确保没有出现分钟数
    60
    ,可以添加一些条件:
    如果(r==60){r=0;$1++}

    $ awk -F"[.:]" -v OFS=":" '{r=sprintf("%d", ($2-1)/5); r=(r+1)*5; if (r==60) {r=0; $1++}; a[$1"."r]+=$3} END {for (i in a) print i, a[i]}' file
    23.0:6
    13.5:4
    12.15:8
    23.5:0
    11.5:22
    
    您还可以做一些奇特的事情,例如打印一个前导
    0
    0分钟:

    再来一杯

    如果你想四舍五入到最接近的5

    awk -F"[.:]" '{$2=(t=($2%5))>2?$2-t+5:$2-t;if($2==60){$1++;$2=0};a[$1]+=$3;b[$1]=$2}
                  END{for(i in b)print i"."b[i]":"a[i]}' file
    
    如果你想把所有不是5的倍数的东西都四舍五入

    awk -F"[.:]" '{$2=$2%5!=0?$2-($2%5)+5:$2;if($2==60){$1++;$2=0};a[$1]+=$3;b[$1]=$2}
                  END{for(i in b)print i"."b[i]":"a[i]}' file
    
    四舍五入至5的最接近倍数的输出 四舍五入到下一个5的倍数 正如您在输出中看到的,这将四舍五入到最接近的5,这就是22.55存在的原因

    四舍五入的工作原理 当一个数除以另一个数时,模数给出余数

    24/5=4剩余4

    所以

    24%5=4

    所以要把数字四舍五入到X的下一个倍数,我们只需减去余数

    N-(N%X)
    24-(24%5)

    将始终是X的倍数(向下舍入)

    为了进行四舍五入,我们简单地说,如果模的结果大于
    X的一半(在本例中为5),则将X与结果相加,以四舍五入到X的下一个倍数

    (N-(N%X))+X
    (24-(24%5))+5


    不确定这是否是进行循环的最佳方式,但它确实有效:)

    是的。因为没有13.01,13.02的数据。我只想在第5分钟内得到输出。您可以详细说明一下,它不是很清楚。@user1580770您不想四舍五入到最接近的5吗?因为
    22.56
    22.57
    都会四舍五入到
    22.55
    @Jidder显然都会四舍五入到上面的5.1,2,3,4和5-->5,而6,7,8,9,0->0。我在回答中做了一个小图表:D@fedorqui我知道,我只是想知道OP是否意识到这就是他们所做的,我在我的答案中添加了这两个,以防万一:)我使用了模数,虽然:D(你的整数除法几乎是mod)04:15,39 04:20,225 04:25,208 04:30,263 04:35,311 04:40,270 04:45,287 04:50,264 04:55,261 5:00,191 05:00,42 05:05,221 05:10,227 05:15,225 05:20,219 05:25,208 05:30,207 05:35,214 05:40,207 05:45,250 05:50,241 05:55,243 6:00,207 06:00,46 06:05,233 06:10,243 06:15,260 06:20,241 06:25,244 06:30,242 06:35,222 06:40,241 06:45,287 06:50,226 06:55,222 7:00,168 07:00,47 07:05438 07:10260 07:15256 07:20290 07:25256 07:30249 07:35249 07:40256 07:45299 07:50244 07:55284 8:00229 08:00,56 08:05283 08:10263 08:15302 08:20154难以从评论中阅读,你能用这个编辑你的问题吗data@user1580770:您的原始输入是
    hh.mm:count
    格式,但您拥有的是re是
    hh:mm,count
    格式,它们都是不同的。我正在进行更改以处理这两种格式,但您应该在问题中澄清这一点。
    awk -F"[.:]" '{$2=$2%5!=0?$2-($2%5)+5:$2;if($2==60){$1++;$2=0};a[$1]+=$3;b[$1]=$2}
                  END{for(i in b)print i"."b[i]":"a[i]}' file
    
    11.5:22
    12.15:8
    22.55:4
    13.5:4
    23.0:2
    
    11.05:22
    12.15:8
    13.5:4
    23.00:6