awk/sed를 사용하여 CSV에서 비표준 날짜 타임스탬프 형식 변경

awk/sed를 사용하여 CSV에서 비표준 날짜 타임스탬프 형식 변경

数十万行のCSVがあり、2番目のフィールドで日付形式を変更しようとしています。また、2番目のフィールドが時々まったく埋められない場合もあることを付け加えたいと思います。悲しい入力形式はDayofWeek MonthofYear DayofMonth Hour:Minute:Second Timezone Year

例:

Mon Jul 03 14:48:54 EDT 2023

私が望む出力形式は次のYYYY-MM-DD HH:MM:SS とおりです。

2023-07-03 14:48:54

私はsedに慣れているので、このsed正規表現を使用して行を置き換えてほぼ正しい形式で指定しましたが、月が数字ではないのは問題です。

sed -E "s/[A-Za-z]{3}\s([A-Za-z]{3})\s([0-9]{2})\s([0-9]{2}:[0-9]{2}:[0-9]{2})\s[A-Z]+\s([0-9]{4})/\4-\1-\2 \3/"

sed置換セクションでdateコマンドを実行するためにキャプチャグループ1を使用することは不可能だと思います(しかし私が間違っている場合は修正してください)。

sedコマンドが完了したら、月を参照してdateコマンドを使用して解析する方法がわからず、出力全体を他のコマンドにパイピングせずに実行するのが最善だと思います。このコマンドは、残りのデータをフォーマットするために使用される長いパイプコマンドのリストの1つです。

awkを使用すると、書式全体を一度に処理できるようですが、実際にはawkをどのように使用するのかわかりません。

タイムスタンプを正しい形式に変換する最も効率的な方法は何ですか?

より多くの文脈でいくつかのコメントを解決するには:

このデータは、csvログデータをファイルに出力するアプリケーションによって生成されます。これは私のアプリケーションではなく、アプリケーションがどのようにログに記録されるかについての設定制御はありません。 CSVは引用符で囲まれず(フィールドのデータにスペースが含まれていても)、空のフィールドには何も含まれません。

csvデータをmysqlデータベースに直接ロードします。タイムゾーンは一般的に良いアイデアですが、データには常にローカルタイムタイムスタンプがあり、データを視覚化するとき(grafana)UTCとして保存してからEDTに変換して時間が変換される理由を確認する必要はありません。 UTCに再びEDTに変換するだけです。)また、各csv行には経度と緯度が含まれています。したがって、戻ってタイムスタンプをUTCに変更したい場合は、現地時間を把握することはできません。

私が行った追加の書式設定はあまりなく、おそらくawkを使って行うことができました(もう一度言っていますが、私はそこの構文に慣れていません)。元のデータは、いくつかのフィールドを入れるためにID列とqoutesを追加する必要があり、2つの異なる形式の2つの日付/時刻フィールドがあることは役に立ちませんでした。だから私の長くてひどいパイプラインは通常次のようになります。

cat file | add ID column | format timestamp in second csv field | format timestamp in third csv field | qoute any field with spaces | replace empty fields with \N > output file

mysqlと空のフィールドに問題があり、明示的なnull文字を追加しました。これを行うより良い方法が明らかになり、プロセス全体が機能するようになったら、それを確認して簡素化します。

皆さんの回答に心から感謝します。

ベストアンサー1

GNU sed では、s///e修飾子を使用して結果文字列を実行できます。

s/.*/date -d "&" +"%F %T"/e

しかし、これより良い方法は、-f各行に新しいプロセスを作成するのではなく、入力行自体を処理するGNU日付フラグを使用することです。

$ TZ=UTC0 date -f /dev/stdin +'%F %T' <<<$'Mon Jul 03 14:48:54 EDT 2023\nTue, 04 Jul 2023 11:30:45 +0100'
2023-07-03 18:48:54
2023-07-04 10:30:45

入力が信頼できない場合でも、この方法はより安全です。

おすすめ記事