Text-Processing

重新格式化日期字元串

  • May 9, 2015

我試圖弄清楚如何重新格式化一個充滿錯誤格式日期的文件。原始碼如下所示:

{"_id":"","timestamp":"Mon Apr 20 08:30:55 +0000 2015"}
{"_id":"","timestamp":"Mon Apr 20 08:32:25 +0000 2015"}
{"_id":"","timestamp":"Mon Apr 20 08:35:39 +0000 2015"}

大約有 300 萬條這樣的條目。我需要將時間戳格式化為 ISO-8601 格式,即: YYYY-MM-DDTHH:mm:ss.mmm<+/-Offset>

我試過這個,它有效:

date -d "Mon Apr 20 08:35:39 +0000 2015" +%FT%T%z

因為我顯然不會手動檢查所有 300 萬個條目,所以我研究了使用 sed 來實現這一點:

cat input.json | sed "s|\"timestamp\":\"\(.*\)\"|\"timestamp\":\"$(date -d \1 +%FT%T%z)\"|g" > output.json

但是,這會列印相同的(錯誤的)輸出,即2015-05-08T01:00:00+0000. 附近有沒有聰明的頭腦可以幫助我?

可以使用它sed,但awk更自然:

awk -F'"' -v OFS='"'  '$8 {cmd="date -d \""$8"\" +%FT%T%z"; cmd | getline $8; close(cmd)} 1' input.json
{"_id":"","timestamp":"2015-04-20T01:30:55-0700"}
{"_id":"","timestamp":"2015-04-20T01:32:25-0700"}
{"_id":"","timestamp":"2015-04-20T01:35:39-0700"}

上面顯示了 -7:00 小時的偏移量。這反映了系統的預設時區。更改 shell 變數TZ將更改預設值。

這個怎麼運作

  • -F'"' -v OFS='"'

這會將輸入和輸出欄位分隔符設置為"

  • $8 {cmd="date -d \""$8"\" +%FT%T%z"; cmd | getline $8; close(cmd)}

作為"欄位分隔符,日期是欄位編號 8。這將使用正確date的命令創建字元串,然後執行將輸出擷取到更新的欄位 8 中的命令。

前面的$8out 表示只有在欄位 8 有非空值時才會執行此部分。例如,這允許空行不受干擾地通過。

  • 1

這是 awk 對“列印這一行”的神秘簡寫。

處理額外的雙引號

因為我們使用"作為欄位分隔符。假設"在時間戳之前有可變數量的。在這種情況下,我們需要將時間戳稱為倒數第二個欄位$(NF-1),而不是第八個欄位$8。在這種情況下:

awk -F'"' -v OFS='"'  '$8 {cmd="date -d \""$(NF-1)"\" +%FT%T%z"; cmd | getline $(NF-1); close(cmd)} 1' input.json

向日期欄位添加自定義格式

$ awk -F'"' -v OFS='"'  '$8 {cmd="date -d \""$(NF-1)"\" +%FT%T%z"; cmd | getline $(NF-1); close(cmd);$(NF-1)="{$date:" $(NF-1) "}"} 1' input.json
{"_id":"","timestamp":"{$date:2015-04-20T01:30:55-0700}"}
{"_id":"","timestamp":"{$date:2015-04-20T01:32:25-0700}"}
{"_id":"","timestamp":"{$date:2015-04-20T01:35:39-0700}"}

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