如何使用 bash 计算时间总和?

如何使用 bash 计算时间总和?

我想知道我的计算机中一系列进程需要花费的总时间来决定我应该在计算机上运行还是在更强大的计算机上运行。因此,我预测每个命令的运行时间。输出看起来像:

process1    00:03:34
process2    00:00:35
process3    00:12:34

如何对第二列求和以获得总运行时间?我可以尝试将每一行插入

awk '{sum += $2 } END { print sum }

但这没有意义,因为这些值不是自然数。

答案1

#!/bin/sh

EPOCH='jan 1 1970'
sum=0

for i in 00:03:34 00:00:35 00:12:34
do
  sum="$(date -u -d "$EPOCH $i" +%s) + $sum"
done
echo $sum|bc

date -u -d "jan 1 1970" +%s给出 0。所以date -u -d "jan 1 1970 00:03:34" +%s给出 214 秒。

答案2

如果您不能(或不想)使用TIMEFORMAT您只需要将时间转换为秒,则将其加在一起。例如通过管道输出:

{                                           
sum=0
while IFS="[ :]" proc_name h m s
do
    let sum+=$((60*($m+60*$h)+$s)) 
done 
echo $sum  
} 

或者,如果您愿意,可以将 last echo-command 交换为

printf "%02d:%02d:%02d\n" $[sum/3600] $[sum/60] $[sum%60]

答案3

更新:

这是一个利用 的dc“输出基础”的新实现。请注意,如果总和超过 60 小时,则会输出空格分隔的值,而不是三个。 (如果总和少于一小时,则只会输出两个空格分隔的值。)

awk '{print $2}' file.txt | tr : \ | dc -f - -e '60o0ddd[+r60*+r60d**+z1<a]dsaxp'

假设输入为小时、分钟、秒的三倍,如问题所示。

提供的输入的输出是:

 16 43

原答案:

让我们用dc您的桌面计算器来完成此操作。它是 的后端bc,尽管通常被认为是神秘的,但它非常灵活。


首先,进行一些预处理,仅给出时间,并将冒号转换为空格:

awk '{print $2}' | tr : ' '

我们也可以使用 Sed 来做到这一点:

sed -En -e 's/^.*([0-9][0-9]):([0-9][0-9]):([0-9][0-9]).*$/\1 \2 \3/p'

我会选择 Awk,tr因为它更简单。上述任一命令都会生成以下格式的干净输出。 (我使用我自己的示例文本,因为我认为它更有趣;它包含时间。您的示例文本也可以。)

$ cat input
9 39 42
8 04 50
7 49 32
10 01 54
7 19 18

给定上述格式的时间,通过以下 Sed 脚本运行它们并将结果通过管道传输到dc如下所示:

sed -e '1s/^/0 /' -e 's/$/ r 60 * + r 60 60 * * + +/' -e '$s/$/ 60 60 * ~ 60 ~ f/' input | dc

(分解以减少横向滚动:)

sed <input \
    -e '1s/^/0 /' \
    -e 's/$/ r 60 * + r 60 60 * * + +/' \
    -e '$s/$/ 60 60 * ~ 60 ~ f/' |
      dc 

输出将按秒、分钟、小时的顺序排列。 (注意这是一个相反的顺序。) 我只是在学习dc,所以这不是一个完美的解决方案,但我认为乍一看还不错dc

示例输入和输出,直接从我的终端粘贴:

$ cat input 
9 39 42
8 04 50
7 49 32
10 01 54
7 19 18
$ sed -e '1s/^/0 /' -e 's/$/ r 60 * + r 60 60 * * + +/' -e '$s/$/ 60 60 * ~ 60 ~ f/' input | dc 
16
55
42
$ 

答案4

这是我的解决方案 - 使用split().打印总时间(以秒为单位):

awk '{
        split($2, tm, ":");
        tottm += tm[3] + tm[2] * 60 + tm[1] * 3600;
    }
    END {
        print tottm;
    }' ptime

以良好的时间格式打印:

awk '{
        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;
    }' ptime

GNU awk 还支持 strftime,但它将使用您当前的时区,因此结果会令人困惑。

相关内容