特定の日付を含むファイルがあり、それをUTC形式に変換したいと思います。だから小さな台本を用意しました。
次のエラーが発生します。
date: option requires an argument -- 'd'
Try `date --help' for more information.
date: extra operand `16:16:53'
私のファイルの内容は次のとおりです。
20191014161653042nmd
20191014161653052egc
20191004081901490egc
20191004081901493nex
20191004081901497nex
20191004081902531nex
20191004081902534ksd
私のコードは次のとおりです
for i in $(cut -f1 Firstfile)
do
echo "$i" > tmpfile
TIME=$(awk '{print substr($1,1,14)}' tmpfile | sed -re 's/^([0-9]{8})([0-9]{2})([0-9]{2})([0-9]{2})$/\1\\ \2:\3:\4/' | xargs date +@%s -d | xargs date -u +"%Y-%m-%dT%H:%M:%S" -d)
MSec=$(awk '{print substr($1,15,3)}' tmpfile)
Msg=$(awk '{print substr($1,18,3)}' tmpfile)
echo -e "$TIME.$MSec $Msg" >> ResultFile
done
コマンドのみを使用すると正常に動作し、目的の結果が得られます。
awk '{print substr($1,1,14)}' tmpfile | sed -re 's/^([0-9]{8})([0-9]{2})([0-9]{2})([0-9]{2})$/\1\\ \2:\3:\4/' | xargs date +@%s -d | xargs date -u +"%Y-%m-%dT%H:%M:%S" -d
私は台本でどんなミスをしましたか? forループのスクリプトを渡すと、なぜ機能しないのですか?
予想される結果:
2019-10-14T20:16:52.042 nmd
2019-10-14T20:16:52.052 egc
2019-10-04T12:19:01.490 egc
など。
答え1
問題は、date
使用するにはあまりにも多くのデータを渡していることですxargs
。また、出力の一部にするために末尾に追加のテキスト文字列を渡さないこともあります。
awk
スクリプトですべての操作を実行することをお勧めします。 GNUawk
とmawk
GNUには、基本的なタイムスタンプ操作のための機能があります。
{
YYYY = substr($1, 1, 4) # year
mm = substr($1, 5, 2) # month
dd = substr($1, 7, 2) # day
HH = substr($1, 9, 2) # hour
MM = substr($1, 11, 2) # minute
SS = substr($1, 13, 2) # seconds
sss = substr($1, 15, 3) # fractional seconds
text = substr($1, 18) # the rest
tm = mktime(sprintf("%s %s %s %s %s %s", YYYY, mm, dd, HH, MM, SS))
printf("%s.%s %s\n", strftime("%Y-%m-%dT%H:%M:%S", tm, 1), sss, text)
}
これは、入力タイムスタンプの個々のコンポーネントを個々の変数として選択する方法を使用しますsubstr()
。次に、Unix時間を計算しmktime()
(入力時間がローカルタイムゾーンにあると仮定し)、適切な形式に変換された(UTC)タイムスタンプ文字列を使用しますstrftime()
。
コードでは、秒の小数部はsss
時間計算の一部ではありませんが、入力から出力にそのまま送信されます。
実行してください:
$ awk -f script.awk file
2019-10-14T14:16:53.042 nmd
2019-10-14T14:16:53.052 egc
2019-10-04T06:19:01.490 egc
2019-10-04T06:19:01.493 nex
2019-10-04T06:19:01.497 nex
2019-10-04T06:19:02.531 nex
2019-10-04T06:19:02.534 ksd
mktime()
strftime()
マニュアルのマニュアルを参照してくださいawk
。
答え2
これはsedとbashを使用するバージョンです。
sed -re 's/^([0-9]{8})([0-9]{2})([0-9]{2})([0-9]{2})(([0-9]{3,}){0,1})([a-z].*)$/D="\1\ \2:\3:\4";M="\5";E="\7"/' /tmp/tmpfile |\
xargs -d'\n' -I=:= bash -c '(=:=;echo $(date -u +"%Y-%m-%dT%H:%M:%S.$M" -d "TZ=\"America/New_York\" $D" ) $E)'
sed 2番目の部分のすべての内容をawk + sed
削除しないように、sedステップを1つだけ実行しました。\
xargsオプションを使用して、引数を使用-I
する場所を指定します{}
。find
日付を2回使用したくない場合は、日付オプションTZ
のオプションを使用してください。-d
America/New_York
ここではタイムゾーンを入力として使用しているため、正しい値に変更する必要があります。