間違った日付でいっぱいのファイルの形式を再指定する方法を見つけようとしています。ソースは次のとおりです。
{"_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
。このジレンマを解決するのに役立つ人はここにいますか?
ベストアンサー1
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時間のオフセットを示しています。これはシステムのデフォルトのタイムゾーンを反映します。シェル変数を変更すると、TZ
デフォルト値が変更されます。
どのように動作しますか?
-F'"' -v OFS='"'
これにより、入力フィールドと出力フィールドの区切り文字がに設定されます
"
。$8 {cmd="date -d \""$8"\" +%FT%T%z"; cmd | getline $8; close(cmd)}
"
フィールド区切り記号で、日付はフィールド番号8です。その後、正しいコマンドを使用して文字列を生成date
し、コマンドを実行して更新されたフィールド8に出力をキャプチャします。前の出力は、
$8
フィールド8にnull以外の値がある場合にのみこのセクションが実行されることを意味します。これにより、たとえば空の線が邪魔にならずに通過することができます。1
これは「この行を印刷してください」のawkの秘密の速記です。
追加の二重引用符の処理
フィールド区切り記号として使用しているためです"
。"
タイムスタンプの前にさまざまな回数があるとします。この場合、タイムスタンプを$(NF-1)
8番目のフィールドではなく2番目から最後のフィールドとして呼び出す必要があります$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}"}