Bash-使用分组依据的时间总和字段

时间:2018-08-20 15:16:30

标签: bash awk

输入:

70|00:00:01
70|00:00:03
180|00:00:01
180|00:00:10
180|00:00:05

必需的输出:

70|00:00:04
180|00:00:16

我有一个有效的代码,但只返回总时间。

awk -F\| '{
            split($2, tm, ":");
            secs += tm[3]; 
            mins += tm[2] + int(secs / 60); 
            hrs += tm[1] + int(mins / 60);
            secs %= 60; mins %= 60;
          }
          END {
              printf "%d:%d:%d\n", hrs, mins, secs;
          }' input

如何调整代码以按第一个字段分组?

4 个答案:

答案 0 :(得分:2)

您可以使用多维数组并在最后进行迭代和打印:

awk -F\| '{
            split($2, tm, ":");
            out[$1]["secs"] += tm[3];
            out[$1]["mins"] += tm[2] + int(out[$1]["secs"] / 60);
            out[$1]["hrs"] += tm[1] + int(out[$1]["mins"] / 60);
            out[$1]["secs"] %= 60; out[$1]["mins"] %= 60;
          }
          END {
              for (time in out){
                    printf "%s|%02d:%02d:%02d\n", time, out[time]["hrs"], out[time]["mins"], out[time]["secs"];
              }
          }' input

我也在这里编辑了您的printf,以便在您的时间输出中包括前导0以匹配输入。

答案 1 :(得分:2)

$ cat tst.awk
BEGIN { FS = "[|:]" }
{ sum[$1] += $4 + 60*$3 + 60*60*$2 }
END {
    for (key in sum) {
        secs = sum[key]
        h = int(secs/(60*60))
        m = int((secs - (h*60*60))/60)
        s = secs % 60
        printf "%s|%02d:%02d:%02d\n", key, h, m, s
    }
}

$ awk -f tst.awk file
70|00:00:04
180|00:00:16

答案 2 :(得分:1)

gawk -F'[:|]' '
{
    arr[$1] = arr[$1] + mktime("1970 1 1 " $2 " " $3 " " $4) + 10800
}
END {
    for(i in arr)
        print i strftime("|%H:%M:%S", arr[i], 1)
}' input.txt

注意:

mktime无法以UTC格式返回结果,因此在我的情况下,将mktime时间戳结果转换为UTC是通过增加3个小时(3600 sec * 3 = 10800)来完成的。您应该选择您的时区值。

输入(测试复杂)

70|00:00:01
70|04:00:03
70|10:00:03
70|02:00:52
70|03:00:03
70|04:00:05
180|00:00:01
180|00:00:10
180|00:00:05

输出

70|23:01:07
180|00:00:16

答案 3 :(得分:0)

解决方案第一: :考虑到您的Input_file是按第一字段排序的,因此可能对您有帮助。

awk -F\| '
prev!=$1 && FNR>1{
  printf "%d|%d:%d:%d\n", prev, hrs, mins, secs
  prev=hrs=mins=secs=""
}
{
  split($2, tm, ":");
  secs += tm[3];
  mins += tm[2] + int(secs / 60);
  hrs += tm[1] + int(mins / 60);
  secs %= 60; mins %= 60;
  prev=$1
}
END{
  if(prev){
    printf "%d|%d:%d:%d\n", prev, hrs, mins, secs
  }
}'   Input_file

解决方案第二: :如果Input_file未按第一字段排序,则可以通过执行sort -t'|' -k1对其进行排序,并将输出也传递给上述代码。

sort -t'|' -nk1 Input_file |
awk -F\| '
prev!=$1 && FNR>1{
  printf "%d|%d:%d:%d\n", prev, hrs, mins, secs
  prev=hrs=mins=secs=""
}
{
  split($2, tm, ":");
  secs += tm[3];
  mins += tm[2] + int(secs / 60);
  hrs += tm[1] + int(mins / 60);
  secs %= 60; mins %= 60;
  prev=$1
}
END{
  if(prev){
    printf "%d|%d:%d:%d\n", prev, hrs, mins, secs
  }
}'