bash 스크립트의 두 파일에 있는 날짜/시간 차이 양식 항목을 계산합니다.

bash 스크립트의 두 파일에 있는 날짜/시간 차이 양식 항목을 계산합니다.

아래와 같이 두 개의 파일(시작됨 및 완료됨)이 있습니다.

시작 파일:

2018-01-30 10:21:41
2018-01-17 12:22:50
2018-06-27 23:09:20
INVALID
INVALID
... for 800 Rows

완료된 파일:

2018-01-30 10:23:54
2018-01-17 13:23:45
2018-06-28 06:10:56
INVALID
INVALID
... for 800 rows

시간 경과를 얻으려면 file2와 file1의 각 줄에 대한 차이 결과를 포함하는 세 번째 파일을 만들어야 합니다.

새로운 세 번째 파일:

00:02:13
01:00:55
07:01:36
INVALID     //Where any instance of invalid in either file remain in the new file.
INVALID

... 800줄

이 명령을 사용하여 수동으로 작동하게 할 수 있었지만 파일을 반복하는 행운은 없었습니다.

string1="10:21:41"
string2="10:23:54"
StartDate=$(date -u -d "$string1" +"%s")
FinalDate=$(date -u -d "$string2" +"%s")
date -u -d "0 $FinalDate sec - $StartDate sec" +"%H:%M:%S"

> 00:02:13 

답변1

한 줄로

while read -r StartDate  && read -r FinalDate <&3; do if [[ ${StartDate} != "INVALID" && ${FinalDate} != "INVALID" ]]; then diff=$(expr $(date -d "${FinalDate}" +"%s") - $(date -d "${StartDate}" +"%s")); printf '%dd:%dh:%dm:%ds\n' $((${diff}/86400)) $((${diff}%86400/3600)) $((${diff}%3600/60)) $((${diff}%60));else echo INVALID; fi; done < startedfile 3<finishedfile

스크립트로

#!/bin/bash

while read -r StartDate  && read -r FinalDate <&3; do 
    if [[ ${StartDate} != "INVALID" && ${FinalDate} != "INVALID" ]]; then 
        diff=$(expr $(date -d "${FinalDate}" +"%s") - $(date -d "${StartDate}" +"%s")); 
        printf '%dd:%dh:%dm:%ds\n' $((${diff}/86400)) $((${diff}%86400/3600)) $((${diff}%3600/60)) $((${diff}%60));
    else 
        echo INVALID; 
    fi; 
done < startedfile 3<finishedfile

다음과 같은 출력이 제공됩니다.

0d:0h:2m:13s
0d:1h:0m:55s
INVALID
0d:7h:1m:36s
INVALID
INVALID

그런 다음 원하는 파일로 출력할 수 있습니다.


편집하다

설명에서 제안한 대로 dateutils패키지를 설치하고 datediff명령을 사용하면 이 작업을 단순화할 수 있습니다.

while read -r StartDate  && read -r FinalDate <&3; do if [[ ${StartDate} != "INVALID" && ${FinalDate} != "INVALID" ]]; then datediff "${StartDate}" "${FinalDate}" -f "%dd:%Hh:%Mm:%Ss";else echo INVALID; fi; done < started.txt 3<finished.txt 

스크립트에서

#!/bin/bash

while read -r StartDate  && read -r FinalDate <&3; do 
    if [[ ${StartDate} != "INVALID" && ${FinalDate} != "INVALID" ]]; then 
        datediff "${StartDate}" "${FinalDate}" -f "%dd:%Hh:%Mm:%Ss";
    else 
        echo INVALID; 
    fi; 
done < startedfile 3<finishedfile

답변2

다음 bash 스크립트를 사용하면 문제를 해결할 수 있다고 생각합니다.

#!/usr/bin/env bash

sfile=/path/to/start
efile=/path/to/end
ofile=/path/to/out
n=0

while read -r line; do
    ((n++))
    if [[ $line == 'INVALID' ]]; then
        echo "INVALID"
        continue
    fi
    start=$(date -u -d "$line" "+%s")
    end=$(date -u -d "$(sed -n "${n}p" "$efile")" "+%s")
    date -u -d "0 $end sec - $start sec" +"%H:%M:%S"
done<"$sfile" >"$ofile"

그러면 시작 파일의 각 줄을 읽고 이를 끝 파일의 일치하는 줄과 비교합니다. 줄에 "INVALID"가 포함되어 있으면 "INVALID"가 표시되고 루프의 다음 반복으로 점프합니다.

답변3

ddiffGNU를 사용 dateutils하고 다음을 수행하십시오 bash.

#!/bin/bash

paste STARTED COMPLETED |
while IFS=$'\t' read start compl; do
    if [ "$start" = "INVALID" ] || [ "$compl" = "INVALID" ]; then
        echo 'INVALID'
    else
        ddiff -f '%0H:%0M:%0S' "$start" "$compl"
    fi
done

입력 파일이 STARTEDand 라고 가정하면 첫 번째 필드에 시작 시간이 있고 두 번째 필드에 종료 시간이 있는 COMPLETED탭으로 구분된 루프 입력이 생성됩니다 . while이를 읽고 두 시간 중 하나가 인지 확인합니다 INVALID. 그렇지 않다면 ddiff그들에게 말을 겁니다.

해당 출력은 파일에 저장될 수 있으며 done스크립트 호출 시 명령줄의 스크립트 이름 끝이나 뒤에 리디렉션될 수 있습니다.

제공된 데이터에 대해 실행합니다.

$ bash script.sh
00:02:13
01:00:55
07:01:36
INVALID
INVALID

답변4

그리고 zsh:

#! /bin/zsh -
# usage: that-script file1 file2
zmodload zsh/datetime
while
  IFS= read -ru3 a &&
   IFS= read -ru4 b
do
  if
    strftime -rs at '%Y-%m-%d %H:%M:%S' "$a" 2> /dev/null &&
      strftime -rs bt '%Y-%m-%d %H:%M:%S' "$b" 2> /dev/null
  then
    d=$((bt - at))
    printf '%02d:%02d:%02d\n' $((d/3600)) $(((d/60)%60)) $((d%60))
  else
     printf '%s\n' $a
  fi
done 3< ${1?} 4< ${2?}

여전히 쉘 루프를 사용하여 텍스트 처리이는 일반적으로 나쁜 습관으로 간주됩니다.그러나 적어도 여기서는 내장 명령만 사용하고 있습니다. 이는 date각 입력 줄에 대해 두 개의 외부 GNU 명령을 호출하는 것만큼 성능이 나쁘지 않음을 의미합니다.

관련 정보