Bash kullanarak zaman nasıl toplanır?


12

Bilgisayarımda bir dizi işlemin orada mı yoksa daha güçlü bir bilgisayarda mı çalışmam gerektiğine karar vermek için alacağı toplam süreyi bilmek istiyorum. Yani, her komutun çalışma süresini tahmin ediyorum. Çıktı şöyle görünür:

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

Toplam çalışma süresi elde etmek için ikinci sütunu nasıl toplayabilirim? Her satırı pipetlemeyi deneyebilirim

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

ancak değerler doğal sayılar olmadığı için bu bir anlam ifade etmiyor.

Yanıtlar:


15
#!/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" +%sBöylece date -u -d "jan 1 1970 00:03:34" +%s214 saniye verir.


Biraz hack-y gibi görünüyor, ama hey, ilginç bir şekilde çalışıyor.
hjk

4

Bash 'time' yerleşik komutunu kullandığınızı varsayarsak, programınızı çalıştırmadan önce bunu yapabilirsiniz export TIMEFORMAT=%0R. Çıktı daha sonra awk ile saniyeler içinde eklenebilir. Daha fazla bilgi bash man sayfasının 'Shell Değişkenleri' bölümünde bulunabilir.


4

TIMEFORMATSüreyi kullanamıyorsanız (veya istemiyorsanız) sadece saniyeye aktarmanız gerekir, ardından birlikte ekleyin. Örneğin boru çıkışı:

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

Veya isterseniz son echo-komut alışverişi yapabilirsiniz

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

Dakikalar $[sum/60%60]saatleri ayırmak olmalıdır.
Jesse Chisholm

3

Güncelleme:

İşte dc's "çıktı tabanı" kullanan yeni bir uygulama . Toplam toplam 60 saatten fazlaysa, bunun üç yerine dört boşlukla ayrılmış değer vereceğini unutmayın . (Toplam toplam bir saatten azsa, yalnızca iki boşlukla ayrılmış değer verilir.)

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

Girişin, soruda gösterildiği gibi, saat, dakika, saniye üç katı olduğu varsayılır.

Sağlanan girişteki çıkış:

 16 43

Orijinal cevap:

Bunu dcMasa Hesap Makinesi ile yapalım . Bu arka uç bcve sık sık şifreli olarak kabul edilse de son derece esnektir.


İlk olarak, bazı zamanlar sadece süreleri vermek ve iki nokta üst üste işaretini boşluklara dönüştürmek için:

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

Bunu Sed ile de yapabiliriz:

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

Awk ile gideceğim ve trdaha basit. Yukarıdaki komutlardan biri, aşağıdaki biçimde temiz bir çıktı üretir. (Kendi örnek metnimi kullanıyorum çünkü daha ilginç buluyorum; saatler dahil. Sizin de çalışacak.)

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

Yukarıdaki formatta verilen süreler, aşağıdaki Sed komut dosyasında çalıştırılır ve sonucu dcgösterildiği gibi aktarılır :

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

(Yan kaydırmayı azaltmak için parçalara ayrıldı :)

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

Çıktı, bu sırayla saniye, dakika, saat olacaktır. (Bu tersine çevrilmiş bir dizidir.) Sadece öğreniyorum, dcbu yüzden bu mükemmel bir çözüm değil, ama ilk bakışta oldukça iyi olduğunu düşünüyorum dc.

Doğrudan terminalimden yapıştırılan örnek giriş ve çıkış:

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

2

İşte benim çözüm - kullanım split(). Toplam süreyi saniye cinsinden yazdırma:

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

Güzel zaman biçiminde baskı:

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 de strftime'ı destekliyor, ancak mevcut saat diliminizi kullanacak, bu nedenle sonuçlar kafa karıştırıcı olacaktır.


Saat dilimi sorununu kaldırmak için gawkile arayabilirsiniz TZ=UTC0 gawk....
Stéphane Chazelas

2

Sadece bölün ve hesaplayın:

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

0

Buradaki temalarda varyasyon, ancak daha fazla boru

echo """
process1    00:03:34
process2    00:00:35
process3    00:12:34
"""  | \
     sed 's/process.  *\([0-9]\)/\1/g' | \
     xargs -i{} date +%s --date "1970-1-1 {}" | \
     awk '{sum += $1; cnt +=1} 
         END {
               print sum / 60, " total minutes processing";
               print (sum / 3600) / cnt, "minutes per job"
         }'
916.717  total minutes processing
5.09287 minutes per job

0

Hemen hemen her kabuk matematik yapabilir:

#!/bin/sh

IFS=:; set +f
getseconds(){ echo "$(( ($1*60+$2)*60+$3 ))"; }

for   t in 00:03:34 00:00:35 00:12:34
do    sum=$((sum + $(getseconds $t) ))
done
printf '%s\n' "$sum"

getseconds $=tBölmek için zsh kullanın .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.