bash中的总持续时间

bash中的总持续时间,bash,perl,awk,Bash,Perl,Awk,我从各自的日志文件中获取文件中各个进程的执行时间。具有执行时间的文件看起来类似于以下内容(它可能有数百个条目) 第一行是hours:minutes:seconds,第二行是minutes:seconds,第三行就是seconds 我想将所有条目相加,得出总执行时间。如何在bash中实现这一点?如果不是bash,那么您可以提供其他脚本语言中的一些示例来计算时间戳吗?最容易阅读的完整perl脚本: use strict; use warnings; my $seconds = 0; while

我从各自的日志文件中获取文件中各个进程的执行时间。具有执行时间的文件看起来类似于以下内容(它可能有数百个条目)

第一行是
hours:minutes:seconds
,第二行是
minutes:seconds
,第三行就是
seconds


我想将所有条目相加,得出总执行时间。如何在bash中实现这一点?如果不是bash,那么您可以提供其他脚本语言中的一些示例来计算时间戳吗?

最容易阅读的完整
perl
脚本:

use strict;
use warnings;

my $seconds = 0;

while (<DATA>) {
    my @fields = reverse(split(/:/));

    for my $i (0 .. $#fields) {
        $seconds += $fields[$i] * 60 ** $i;
    }
}

print "$seconds\n";

__DATA__
1:00:01.11
2:2.20
1.02
输出:

3724.33
01:02:04
在这两种情况下,我们都将H:M:S分隔符上的每一行拆分
,然后反转数组,以便从右到左进行处理。为了得到以秒为单位的总时间,我们可以使用一个巧妙的技巧,将每个场乘以60的幂

如果您希望以H:M:S格式而不是原始秒数显示结果,POSIX核心模块将简化:

use POSIX qw(strftime);
print strftime('%H:%M:%S', gmtime($seconds)), "\n";
输出:

3724.33
01:02:04
要使用(POSIX兼容的)awk解决方案作为补充:

awk -F: '{ n=0; for(i=NF; i>=1; --i) secs += $i * 60 ^ n++ } END { print secs }' file
对于示例输入,此输出(所有时间跨度的总和,以秒为单位):

有关如何将此值格式化为时间跨度的信息,请参见以下部分,类似于输入(
01:02:04.33

说明:

  • -F:
    将输入行拆分为字段,以便生成的字段(
    $1
    $2
    ,…)分别表示小时、分钟和秒分量

  • n=0;for(i=NF;i>=1;--i)secs+=$i*60^n++
    按相反顺序枚举字段(如果定义,先是秒,然后是分钟,然后是小时;
    NF
    是字段数),并将每个字段乘以60的适当倍数,以秒为单位生成一个总值,存储在变量
    secs
    中,不断地跨越界限

  • END{print secs}
    在处理完所有行后执行,只需以秒为单位打印累积值


将输出格式化为时间跨度: 必须使用自定义输出格式:

awk -F: '
  { n=0; for(i=NF; i>=1; --i) secs += $i * 60 ^ n++ }
  END { 
    hours   = int(secs / 3600)
    minutes = int((secs - hours * 3600) / 60)
    secs    = secs % 60
    printf "%02d:%02d:%05.2f\n", hours, minutes, secs
  }
' file
上述产量(相当于
3724.33
s):

END{…}
块将
secs
中累积的总秒数拆分为小时、分钟和秒,并使用
printf
输出具有组件适当格式的结果

无法使用诸如
date
和GNU
awk
的(非标准)日期格式化函数等实用程序格式化输出的原因有两个:

  • 标准时间格式说明符
    %H
    在24小时内结束,因此如果累计时间跨度超过24小时,则输出将不正确

  • 分数秒将丢失(Unix时间戳的粒度为整秒)


坦率地说,除了从单独文件中的日志文件中获取执行时间外,没有尝试任何时间戳的总和。我搜索了stackexchange和相关论坛,找到了一些示例,但我不知道我可以使用什么逻辑来区分第一行、第二行和第三行(根据我问题中的示例),因为不是每行都有全部3…小时:分钟:如果最终输出可以解析为h、m、s,那么secondsIt会更好,尽管——不管怎样,答案不错;趴下@“好的,”他补充道。作为一名自豪的野猫校友,我觉得必须给出100%的解决方案;-)或者甚至在循环中包含相反的内容。总体而言,这是一个优雅的解决方案,但在使用
strftime
格式化输出时有两个注意事项:如果总时间跨度超过24小时,
%H
将自动结束,结果将不正确-尝试将
23:59:59
添加到输入中。此外,分数秒也会丢失。后者可能不是问题,但前者与包含数百个时间戳的文件有关,正如OP所述。@mklement0我同意。没有额外的信息很难确定,但我可以在以后随时更新答案。
awk -F: '
  { n=0; for(i=NF; i>=1; --i) secs += $i * 60 ^ n++ }
  END { 
    hours   = int(secs / 3600)
    minutes = int((secs - hours * 3600) / 60)
    secs    = secs % 60
    printf "%02d:%02d:%05.2f\n", hours, minutes, secs
  }
' file
01:02:04.33