bash를 사용하여 시간을 합산하는 방법?


12

일련의 프로세스가 컴퓨터에서 실행해야하는지 아니면 더 강력한 컴퓨터에서 실행해야하는지 결정하는 데 걸리는 총 시간을 알고 싶습니다. 그래서 각 명령의 실행 시간을 예측하고 있습니다. 결과는 다음과 같습니다.

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

총 실행 시간을 얻기 위해 두 번째 열을 어떻게 합산 할 수 있습니까? 나는 각 라인을 통해 엿볼 수 있습니다

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

그러나 값이 자연수가 아니기 때문에 의미가 없습니다.

답변:


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" +%s0 그래서 제공 date -u -d "jan 1 1970 00:03:34" +%s214 초를 제공합니다.


조금 해킹처럼 보이지만 재미있는 (정렬 한) 방식으로 작동합니다.
hjk

4

bash 'time'내장 명령을 사용한다고 가정하면 프로그램을 실행하기 전에 다음을 수행 할 수 있습니다 export TIMEFORMAT=%0R. 그러면 출력은 awk로 추가 할 수 있습니다. 자세한 내용은 bash 매뉴얼 페이지의 'Shell Variables'섹션에서 확인할 수 있습니다.


4

TIMEFORMAT시간을 초 단위로 전송하기 만하면됩니다 (또는 원하지 않는 경우) . 예를 들어 파이프 출력 :

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

또는 원하는 경우 마지막 echo명령을 교환 할 수 있습니다

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

분은 $[sum/60%60]시간을 제거 해야합니다 .
제시 Chisholm

3

최신 정보:

다음은 dc'출력 기반' 을 사용하는 새로운 구현입니다 . 총 합계가 60 시간을 초과하면 3이 아닌 4 개의 공백으로 구분 된 값 이 출력됩니다 . (총합이 1 시간 미만인 경우 공백으로 구분 된 두 값만 출력됩니다.)

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

질문에 표시된 것처럼 입력은시, 분, 초의 3 배로 가정합니다.

제공된 입력의 출력은 다음과 같습니다.

 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
$ 

2

여기 내 솔루션 사용 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도 지원하지만 현재 시간대를 사용하므로 결과가 혼란 스러울 수 있습니다.


표준 시간대 문제를 제거하기 위해 전화 gawk를 걸 수 있습니다 TZ=UTC0 gawk....
Stéphane Chazelas

2

그냥 나누고 계산하십시오.

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

0

여기 테마에 대한 변형이지만 더 많은 파이프

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

거의 모든 쉘이 수학을 수행 할 수 있습니다.

#!/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 $=tzsh에서 사용 하여 분할하십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.