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++
是字段数),并将每个字段乘以60的适当倍数,以秒为单位生成一个总值,存储在变量NF
中,不断地跨越界限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
和GNUawk
的(非标准)日期格式化函数等实用程序格式化输出的原因有两个:
- 标准时间格式说明符
在24小时内结束,因此如果累计时间跨度超过24小时,则输出将不正确%H
- 分数秒将丢失(Unix时间戳的粒度为整秒)
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