변수를 통해 bash 스크립트에서 날짜 명령을 사용하는 방법

변수를 통해 bash 스크립트에서 날짜 명령을 사용하는 방법

특정 날짜가 포함된 파일이 있는데 이를 UTC 형식으로 변환하고 싶습니다. 그래서 작은 대본을 준비했어요

다음 오류가 발생합니다.

date: option requires an argument -- 'd'
Try `date --help' for more information.
date: extra operand `16:16:53'

내 파일 내용은 다음과 같습니다.

20191014161653042nmd
20191014161653052egc
20191004081901490egc
20191004081901493nex
20191004081901497nex
20191004081902531nex
20191004081902534ksd

내 코드는 다음과 같습니다

for i in $(cut -f1 Firstfile)
do
echo "$i" > tmpfile
TIME=$(awk '{print substr($1,1,14)}' tmpfile | sed -re 's/^([0-9]{8})([0-9]{2})([0-9]{2})([0-9]{2})$/\1\\ \2:\3:\4/' | xargs date +@%s -d | xargs date -u +"%Y-%m-%dT%H:%M:%S" -d)
MSec=$(awk '{print substr($1,15,3)}' tmpfile)
Msg=$(awk '{print substr($1,18,3)}' tmpfile)
echo -e "$TIME.$MSec $Msg" >> ResultFile
done

명령만 사용하면 제대로 작동하고 원하는 결과를 얻습니다.

awk '{print substr($1,1,14)}' tmpfile | sed -re 's/^([0-9]{8})([0-9]{2})([0-9]{2})([0-9]{2})$/\1\\ \2:\3:\4/' | xargs date +@%s -d | xargs date -u +"%Y-%m-%dT%H:%M:%S" -d

내가 대본에서 어떤 실수를 했나요? for 루프의 스크립트를 통해 전달할 때 왜 작동하지 않습니까?

예상되는 결과:

2019-10-14T20:16:52.042 nmd
2019-10-14T20:16:52.052 egc
2019-10-04T12:19:01.490 egc

등.

답변1

문제는 date사용 하기에 너무 많은 데이터를 전달하고 있다는 것입니다 xargs. 또한 출력의 일부로 만들기 위해 끝에 추가 텍스트 문자열을 전달하지 않는다는 것입니다.

awk스크립트에서 모든 작업을 수행하는 것이 좋습니다 . GNU awkmawkGNU에는 모두 기본 타임스탬프 작업을 위한 기능이 있습니다.

{
        YYYY    = substr($1, 1, 4)   # year
        mm      = substr($1, 5, 2)   # month
        dd      = substr($1, 7, 2)   # day
        HH      = substr($1, 9, 2)   # hour
        MM      = substr($1, 11, 2)  # minute
        SS      = substr($1, 13, 2)  # seconds
        sss     = substr($1, 15, 3)  # fractional seconds

        text    = substr($1, 18)     # the rest

        tm = mktime(sprintf("%s %s %s %s %s %s", YYYY, mm, dd, HH, MM, SS))
        printf("%s.%s %s\n", strftime("%Y-%m-%dT%H:%M:%S", tm, 1), sss, text)
}

이는 입력 타임스탬프의 개별 구성 요소를 개별 변수로 선택하는 방법을 사용합니다 substr(). 그런 다음 Unix 시간을 계산하고 mktime()(입력 시간이 현지 시간대에 있다고 가정) 적절한 형식으로 변환된 (UTC) 타임스탬프 문자열을 사용합니다 strftime().

코드에서 초의 분수 부분은 sss시간 계산의 일부가 아니지만 입력에서 출력으로 그대로 전송됩니다.

실행하세요:

$ awk -f script.awk file
2019-10-14T14:16:53.042 nmd
2019-10-14T14:16:53.052 egc
2019-10-04T06:19:01.490 egc
2019-10-04T06:19:01.493 nex
2019-10-04T06:19:01.497 nex
2019-10-04T06:19:02.531 nex
2019-10-04T06:19:02.534 ksd

mktime()strftime()설명서 의 설명서를 참조하십시오 awk.

답변2

이것은 sed와 bash를 사용하는 버전입니다.

 sed -re 's/^([0-9]{8})([0-9]{2})([0-9]{2})([0-9]{2})(([0-9]{3,}){0,1})([a-z].*)$/D="\1\ \2:\3:\4";M="\5";E="\7"/' /tmp/tmpfile  |\ 
  xargs -d'\n' -I=:= bash -c  '(=:=;echo $(date -u +"%Y-%m-%dT%H:%M:%S.$M" -d "TZ=\"America/New_York\" $D" )  $E)'

sed 두 번째 부분의 모든 내용을 awk + sed
삭제 하지 않기 위해 sed 단계를 1개만 수행했습니다.\

xargs 옵션을 사용하여 -I인수를 사용할 위치를 지정합니다 {}.find

날짜를 두 번 사용하지 않기 위해 날짜 옵션 TZ의 옵션을 사용합니다.-d

America/New_York여기서는 시간대를 입력으로 사용하고 있으므로 이를 올바른 값으로 변경해야 합니다.

관련 정보