awkを使用してyyyymmddhhmmssに1秒を追加します。

awkを使用してyyyymmddhhmmssに1秒を追加します。

7番目のフィールドがyyyymmddhhmmssのこのファイルがあります。この数字を1秒ずつ増やす必要があります。

これまで私は見つけました:

awk 'BEGIN{FS=OFS="|"} $7=$7+1 ' <file> 

うまくいくようですが... 7番目のフィールドの最後の2桁の数字が「59」の場合は、明らかに「60」に置き換えられます。

列全体を1秒ずつ増やすためにフィールドが日付であることをawkに通知する方法はありますか?

現在のファイル

09099458|1|000|41181|0|0|20221130164738|67
82060649|1|000|36827|0|0|20221130172359|67

予想される結果

09099458|1|000|41181|0|0|20221130164739|67
82060649|1|000|36827|0|0|20221130172400|67  <- From 17:23:59 to 17:24:00

よろしくお願いします。

ベストアンサー1

GNUを使用awkする@トーマスディキmawk1:

$ gawk -F'|' -v OFS='|' '{
   gsub("..", "& ", $7)
   sub(" ", "", $7)
   $7 = strftime("%Y%m%d%H%M%S", mktime($7) + 1)
   print}' < your-file
09099458|1|000|41181|0|0|20221130164739|67
82060649|1|000|36827|0|0|20221130172400|67

呼び出しは、目的の形式を取得するために最初のスペースを削除しますgsub()。後者はこれをUNIX時代に変換します。 1を追加し、YYYYmmddHHMMSSにフォーマットを変更します。"20221130164739""20 22 11 30 16 47 39 "sub()"2022 11 30 16 47 39 "mktime()

awkサポートしていない場合は、/mktime()いつでもコアモジュールをstrftime()使用できます。perlTime::Piece

perl -MTime::Piece -F'\|' -lase '
  $F[6] = (Time::Piece->strptime($F[6], $format) + 1) -> strftime($format);
  print join "|", @F' -- -format=%Y%m%d%H%M%S < your-file

ここでは、入力文字列を日付として解析するために、標準のC関数と同じ名前の関数を使用しますTime::Piecestrptime()これにより、ソリューションを他の日付形式に簡単に適応させることができます(移動性が向上します)。

両方がないgawk場合、一部のシェル(zshやksh93など)には、日付/時刻の解析と書式設定機能が組み込まれています。mawkperl

たとえば、zsh次のようになります。

zmodload zsh/datetime
format=%Y%m%d%H%M%S
while IFS='|' read -ru3 -A fields; do
  strftime -rs t $format $fields[7] &&
    strftime -s 'fields[7]' $format $(( t + 1 ))
  print -r -- ${(j[|])fields}
done 3< your-file

1以降バージョン 20121129この記事を書いた時点で、リリースはほぼ正確に10年前でした。

おすすめ記事