Text-Processing
重新格式化日期字元串
我試圖弄清楚如何重新格式化一個充滿錯誤格式日期的文件。原始碼如下所示:
{"_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 中的命令。前面的
$8
out 表示只有在欄位 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}"}