awk를 사용하여 타임스탬프를 변환할 때 날짜가 잘못되었습니다.

awk를 사용하여 타임스탬프를 변환할 때 날짜가 잘못되었습니다.

로그 파일의 타임스탬프를 Unix 타임스탬프로 변환하는 방법을 찾으려고 합니다. 지금까지 내가 생각해낸 명령은 다음과 같습니다.

awk -F'[' '{ print $2}' | awk -F']' '{cmd ="date \"+%s\" -d \""$1"\""; cmd | getline var; print var $2; close(cmd)}'

이 명령은 원래 타임스탬프에 UTC가 시간대로 포함되어 있거나 시간대가 지정되지 않은 경우에 작동합니다. 그러나 시간대가 다른 값이면 실패합니다. 예를 들어 다음과 같이 작동합니다.

$ entry="[08-May-2020 15:40:32 UTC] PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290"
$ echo "$entry" | awk -F'[' '{ print $2}' | awk -F']' '{cmd="date \"+%s\" -d \""$1"\""; cmd | getline var; print var $2; close(cmd)}'
1588952432 PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290

이 명령은 시간대가 지정되지 않은 경우에도 작동합니다.

$ entry="[08-May-2020 15:40:32] PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290"
$ echo "$entry" | awk -F'[' '{ print $2}' | awk -F']' '{cmd="date \"+%s\" -d \""$1"\""; cmd | getline var; print var $2; close(cmd)}'
1588948832 PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290

그러나 Europe/London시간대가 다음과 같은 경우에는 실패합니다.

$ entry="[08-May-2020 15:40:32 Europe/London] PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290"
$ echo "$entry" | awk -F'[' '{ print $2}' | awk -F']' '{cmd="date \"+%s\" -d \""$1"\""; cmd | getline var; print var $2; close(cmd)}'
date: invalid date ‘08-May-2020 15:40:32 Europe/London’
 PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290

awk 명령을 디버깅하는 방법을 잘 모르겠습니다. 시간대의 슬래시가 마음에 들지 않을 수도 있지만 이는 단지 추측일 뿐입니다.

답변1

date가 TZ 변수를 수신하고 이를 이해하는 방식은 까다롭습니다. 이 명령의 작동 방식:

 $ date -d 'TZ="UTC" 08-May-2020 15:40:32' +"%s"
1588952432

Olson 데이터베이스의 TZ:

$ date -d 'TZ="Europe/London" 08-May-2020 15:40:32' +"%s" 
1588948832

그리고 에포크 시간이 다르다는 점에 유의 1588952432하세요 1588948832. 런던 과 UTC -1의 시차가 1시간이기 때문입니다 0.

형식이 매우 엄격하다는 점을 이해하세요. 먼저 TZ, 모든 것이 작은따옴표로 묶여 있고 TZ 값도 큰따옴표로 묶여 있습니다. 그리고 너무 엄격해서 취약하기도 합니다.

따라서 배열에 값을 설정합니다(bash, ksh 또는 zsh 가정).

entry=( 
        "[08-May-2020 15:40:32 UTC] PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290"
        "[08-May-2020 15:40:32] PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290"
        "[08-May-2020 15:40:32 Europe/London] PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290"
      )

그런 다음 awk를 사용하여 날짜의 모든 값을 가져올 수 있습니다. (FS는 awk에 대한 한 번의 호출에서 다르며(기술적으로는 GNU awk 또는 nawk) 시간 문자열의 요소 수가 다르기 때문에 분할이 사용됩니다. ):

printf '%s\n' "${entry[@]}" | awk -F '[][]' '{
    n=split($2, val, / /, sep);
    cmd=sprintf("date +\"%%s\" -d '\''TZ=\"%s\" %s %s'\''",val[3],val[1],val[2]);
    cmd | getline var; close(cmd);
    print "["var"]"$3;
}'
[1588952432] PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290
[1588952432] PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290
[1588948832] PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290

기술적으로 라인은 다음과 같습니다.

if ( (rc=(cmd | getline var)) != 1){ 
     print "error on calling the command date ",rc; exit 
};

getline의 일부 오류는 포착되지만(기본적으로 getline은 명령에서 출력을 얻을 수 없음), awk는 명령의 오류 번호를 보고하거나 이에 대한 조치를 취할 수 없습니다. 필요한 경우 실행을 중단하는 것은 명령의 책임입니다. awk가 수행하는 유일한 작업(오류 여부)은 cmd의 stderr 출력을 stderr로 직접 파이프하는 것입니다. 따라서 awk의 stderr에 대한 명령으로 인해 발생한 모든 설명(또는 오류)을 볼 수 있습니다. 필요한 경우 이를 검토하고 해결하세요. 그렇지 않으면 출력 파일이 자동으로 손상됩니다. 당신은 경고를 받았습니다! . 이것이 당신이 요구하는 것 같습니다.

아니요, awk는 datetime()Olson 데이터베이스의 값은 물론이고 TZ 시간도 이해할 수 없습니다.

답변2

[date+time]@Isaac이 올바른 방향으로 가고 있습니다. 입력 내용에 맞을 수 있으므로 그의 대답을 허용된 답변으로 남겨두십시오. 그러나 입력이 예상 문자열로 시작하지 않거나 호출이 date실패하거나 실패하는 경우를 잡기 위해 그렇게 할 것입니다. 따라서 getline메시지 텍스트의 타임스탬프 뒤에 가 있으면 호출이 성공하고 실행의 일부가 실패하면 실패한 종료 상태로 종료됩니다.]

$ cat tst.awk
match($0,/\[[^]]+] /) {
    dt  = substr($0,RSTART+1,20)
    tz  = substr($0,RSTART+22,RLENGTH-24)
    msg = substr($0,RSTART+RLENGTH)

    cmd = sprintf("date -d \047TZ=\"%s\" %s\047 +\047%%s\047", tz, dt)
    cmd | getline secs
    close(cmd)
}
secs == "" {
    printf "%s[%d]: failed to convert: \"%s\"\n", FILENAME, NR, $0 | "cat>&2"
    exit 1
}
{ print secs, msg; secs="" }

예를 들어 다음 입력 파일이 있다고 가정합니다(마지막 두 줄에 유의하세요. 첫 번째 줄은 ]메시지 섹션에 있고 두 번째 줄은 잘못된 날짜를 가집니다).

$ cat file
[08-May-2020 15:40:32 UTC] PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290"
[08-May-2020 15:40:32] PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290
[08-May-2020 15:40:32 Europe/London] PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 290
[08-May-2020 15:40:32 Europe/London] PHP Warning:  array foo[] is bad, the sky is falling
[08-Bob-2020 15:40:32 Europe/London] PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 290

$ awk -f tst.awk file
1588952432 PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290"
1588952432 PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 1290
1588948832 PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 290
1588948832 PHP Warning:  array foo[] is bad, the sky is falling
date: invalid date ‘TZ="Europe/London" 08-Bob-2020 15:40:32’
file[5]: failed to convert: "[08-Bob-2020 15:40:32 Europe/London] PHP Warning:  Illegal string offset 'ID' in /home/example/public_html/wp-content/themes/example/functions.php on line 290"

$ echo "$?"
1

실패 상태로 종료하는 마지막 부분이 중요하므로 이와 같은 스크립트를 작성할 수 있고 awk 'script' file > tmp && mv tmp file실패하더라도 awk 출력이 입력 파일을 덮어쓰는 것에 대해 걱정할 필요가 없거나 다른 방법으로 결과를 테스트할 수 있습니다.awk 'script' file

관련 정보