Comment additionner le time en utilisant bash?

Je veux connaître le time total qu'une série de process prendrait dans mon ordinateur pour décider si je devrais courir là-bas ou dans un ordinateur plus fort. Donc, je prévois le time de fonctionnement de chaque command. La sortie ressemble à:

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

Comment puis-je additionner la deuxième colonne pour get un time de fonctionnement total? Je pourrais essayer de piquer chaque ligne à travers

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

mais cela n'a aucun sens car les valeurs ne sont pas des nombres naturels.

 #!/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 donne 0. Donc, date -u -d "jan 1 1970 00:03:34" +%s donne 214 secs.

En supposant que vous utilisez la command embeddede bash 'time', avant d'exécuter votre programme, vous pouvez export TIMEFORMAT=%0R . La sortie sera alors en secondes entières additionnelles par awk. Plus d'informations sont disponibles dans la section 'Shell Variables' de la page de manuel bash.

Si vous ne pouvez pas (ou ne voulez pas) utiliser TIMEFORMAT vous suffit de transférer le time en secondes, puis de l'append set. Par exemple, la sortie de tuyau à travers:

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

Ou si vous souhaitez échanger la dernière command echo par

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

Voici ma solution – utilisez split() . Impression du time total en secondes:

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

Impression en format agréable:

 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 supporte également strftime, mais il utilisera votre timezone actuel, donc les résultats seraient déroutants.

Juste split et calculer:

 awk -F '[ :]' ' {sum += $NF + 60 * ($(NF-1) + 60 * $(NF-2))} END {print sum}' 

Faisons cela avec dc votre calculasortingce de bureau. C'est le back-end de bc , et c'est extrêmement flexible bien que souvent considéré comme énigmatique.


Tout d'abord, un pré-traitement pour ne donner que les time, et convertir les deux-points en espaces:

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

Nous pourrions aussi le faire avec Sed:

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

Je vais aller avec Awk et tr parce que c'est plus simple. L'une des commands ci-dessus produit une sortie propre au format suivant. (J'utilise mon propre exemple de text parce que je le trouve plus intéressant, il comprend des heures, et le vôtre aussi.)

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

Donné fois dans le format ci-dessus, lancez-les à travers le script Sed suivant et canaliser le résultat en dc comme indiqué:

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

(Décomposé pour réduire le défilement latéral 🙂

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

La sortie sera en secondes, minutes, heures, dans cette séquence. (Notez qu'il s'agit d'une séquence inverse.) J'apprends simplement dc donc ce n'est pas une solution parfaite, mais je pense que c'est plutôt bon pour un premier coup d'oeil à dc .

Exemple d'input et de sortie, collé directement depuis mon terminal:

 $ 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 $