Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash-使用group by的时间字段总和_Bash_Awk - Fatal编程技术网

Bash-使用group by的时间字段总和

Bash-使用group by的时间字段总和,bash,awk,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 如何调整代码以按第1个字段进行分组?解决方案第1个:考虑到您的输入文件是按第一个字段排序的,下面可能会对您有所帮助 awk -F\| '{ split($2, tm, ":"); secs += tm[3];

输入:

所需输出:

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
如何调整代码以按第1个字段进行分组?

解决方案第1个:考虑到您的输入文件是按第一个字段排序的,下面可能会对您有所帮助

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
解决方案2:如果您的输入文件未按第一个字段排序,您可以通过执行
sort-t'|'-k1
对其进行排序,并将输出传递给上述代码

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
解决方案一:考虑到您的输入文件是按以下第一个字段排序的,可能会对您有所帮助

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
解决方案2:如果您的输入文件未按第一个字段排序,您可以通过执行
sort-t'|'-k1
对其进行排序,并将输出传递给上述代码

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

您可以使用多维数组,只需在末尾进行迭代和打印:

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
  }
}'

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

您可以使用多维数组,只需在最后迭代并打印:

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
  }
}'
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以匹配输入

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
注意:

mktime
无法以UTC格式返回结果,因此在我的例子中,通过添加3小时(
3600秒*3=10800
)即可将
mktime
时间戳结果转换为UTC。你应该选择你的时区值

输入(测试复杂)

输出

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
注意:

mktime
无法以UTC格式返回结果,因此在我的例子中,通过添加3小时(
3600秒*3=10800
)即可将
mktime
时间戳结果转换为UTC。你应该选择你的时区值

输入(测试复杂)

输出

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

你可以通过使用
-F[:|]
:)来保存自己的
拆分
)哦,是的,完全是@PesaThe,这是一个很好的添加。我认为
-F[:\ \124;]
虽然要避开
regex元字符。嗯,我认为在
[…]
中没有必要这样做。我得到了一个
awk:fatal:不匹配[,[^,[:,[,或[=:/[:/
没有它。也许这取决于awk版本或其他什么。你应该提到的是,考虑到真正的多维数组语法,它只能在GNU awk中工作。你可以通过使用
-F[:]
:)来保存自己的
拆分
,哦,是的@PesaThe,这是一个很好的补充。我认为
-F[:\]
虽然要避开
|
regex元字符.Hmm,但我认为在
[…]中没有必要这样做。
我得到了一个
awk:fatal:Unmatched[,[^,[:,[,或[=:/[:/
没有它。可能这取决于awk版本或其他什么。你应该提到的是,考虑到真正的多维数组语法,这只在GNU awk中有效。不客气。请参阅了解下一步要做什么。不客气。请参阅了解下一步要做什么。