AWKによる時刻列の付加

10Hzでサンプリングされた計測データの時系列observed.txtが有ります。

-1.2272064388e-01
6.5884366632e-03
1.5742965043e-01
2.7226161957e-01
3.1432914734e-01
2.7226161957e-01
1.5742965043e-01
6.5884534270e-03
-1.2272065133e-01
-1.7943170667e-01
-1.5418088436e-01
-8.6262218654e-02
-2.9445931315e-02
-8.7659284472e-03
-1.0812029243e-02
-2.2155188024e-01
-3.1715303659e-01
-2.1832183003e-01
1.0541967303e-01
4.8117116094e-01
6.4801311493e-01
4.8117113113e-01
1.0541968048e-01
-2.1832181513e-01
-3.1715306640e-01
-2.2155188024e-01
-8.3830565214e-02
-1.6459558159e-02
-1.8891192973e-02
-3.1877607107e-02

この1行目の計測時刻はファイル名やヘッダー情報などから2017年11月29日9時18分04秒であると分かっているとします。

このデータの1列目に各行の計測時刻を付け加えるためには、

#!/bin/bash
# 時系列データに時刻列を付加する
start_time="2017-11-29 9:18:04"
freq=10

# start_timeをエポック秒に変換する
epoch=`date -d "${start_time}" +'%s'`

cat observed.txt|\
awk --assign freq="$freq" epoch="$epoch"\
'{printf "%s.%03d %s\n",\
 strftime("%FT%H:%M:%S",epoch+(NR-1)/freq),\
 ((NR-1)*1000/freq)%1000,\
 $1}'

とします。dateコマンドで%sフォーマットを指定すると、2017年11月29日9時18分04秒のエポック秒が得られます。エポック秒というのは1970年年頭からの経過秒数だか何かだったと思いますが、このエポック秒を第2引数としてstrftime()という関数がawkの中で使用できます。

ただし小数点以下の秒は表示出来ないため

( (NR-1)*1000/freq )%1000 

 を使用して別途小数点以下の秒数を計算しています。ここで1000としてるのは、フォーマット文で"%03d"(ゼロ詰め三桁)を指定しているからで、マイクロ秒まで表示したい場合は1,000の代わりに1,000,000として"%06d"を指定して下さい。

f:id:S_E_Hyphen:20171129091350p:plain

ただし、strftimeが使用できるのはgawkだけだそうです。同じawkをインストールしているものと思い込んでいたので、テスト機で上手くいったのに実機でエラーが出て唖然としました。

manを叩けばよかったのですが、テスト機がgawk、実機がoriginal-awkをインストールしていることに気付くまで暫く時間がかかってしまいました。