Awk

使用 awk 轉換時間戳時日期無效

  • May 10, 2020

我正在嘗試找到一種將日誌文件中的時間戳轉換為 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 命令。我懷疑它可能不喜歡時區的斜線,但這只是一個猜測。

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. 由於倫敦-1和 UTC 之間存在一 (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 從 date 獲取所有值(請注意,僅一次呼叫 awk(技術上講:GNU awk 或 nawk)的不同 FS 以及由於時間字元串的元素數量不同而使用 split):

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 上看到該命令引發的任何註釋(或錯誤)。如果需要,請務必檢查和處理這些內容。如果沒有,輸出文件將被靜默損壞。你被警告了!。這似乎是你所要求的。

不,awkdatetime()無法理解 TZ 時間,甚至無法理解 Olson 數據庫中的值。

引用自:https://unix.stackexchange.com/questions/585398