次の形式の3列データがあります。
TIME MPID CPID
14:00:04.909 10048 370007
14:00:05.320 10048 370007
14:00:05.462 10048 370008
14:00:05.761 10048 370008
14:00:05.809 10048 370009
14:00:05.833 10048 370009
14:00:11.320 10048 370010
14:00:11.453 10048 370010
14:00:11.693 10048 370011
14:00:13.097 10048 370012
14:00:14.124 10048 370012
ここで、TIME列はHH:MM:SS.SSS形式のタイムスタンプで構成されています。 MPID および CPID 列は識別番号です。その意味は私の質問にとって重要ではありません。 MPID値もデータセットに存在し、出力に伝播する必要があることを除いては機能しません。
私が望むのは、CPID値が一致する行のペアを識別し、その時間の差を計算することです。たとえば、上記の例には、CPIDが77846の2行(3行目と4行目)があります。その時間は14:00:05.320と14:00:05.589なので、違いを計算したいです。 14:00:04.909 - 14:00:05.320 = 00:00:00.589
また、この結果を次の形式で出力したいと思います。
MPID 10051 CPID 77846 Total time difference: 589 mili seconds
与えられたCPIDがデータセットに正確に2回表示されない場合は、それを無視したいと思います。
サンプルデータが与えられた場合、希望の出力は次のようになります。
MPID 10051 CPID 77845 Total time difference: 1400 milli seconds
MPID 10051 CPID 77846 Total time difference: 1300 milli seconds
MPID 10051 CPID 77847 Total time difference: 800 milli seconds
MPID 10051 CPID 77848 Total time difference: 1800 milli seconds
MPID 10051 CPID 77849 Total time difference: 1900 milli seconds
現在使用されているスクリプト:
uniq -D -f 2 "${1}" |
while read a b c && read d e f ; do
g=$(( $(date -d $d +%s) - $(date -d $a +%s) ))
printf "MPID %s CPID %s Total time difference: %02i seconds\n" $b $c $g
done
出力は
MPID 10051 CPID 77845 Total time difference: 00 seconds
MPID 10051 CPID 77846 Total time difference: 03 seconds
MPID 10051 CPID 77847 Total time difference: 12 seconds
MPID 10051 CPID 77848 Total time difference: 15 seconds
MPID 10051 CPID 77849 Total time difference: 19 seconds
答え1
3つの同じ行を追加して、その行が拒否されたことを示し、「正確に2回」の要件を満たすようにCPID
サンプルデータを調整しました。また、私たちが望むペアである370013
2行を追加しました。CPID
370014
TIME MPID CPID
14:00:04.909 10048 370007
14:00:05.320 10048 370007
14:00:05.462 10048 370008
14:00:05.761 10048 370008
14:00:05.809 10048 370009
14:00:05.833 10048 370009
14:00:11.320 10048 370010
14:00:11.453 10048 370010
14:00:11.693 10048 370011
14:00:13.097 10048 370012
14:00:14.124 10048 370012
14:00:14.189 10048 370013
14:00:14.320 10048 370013
14:00:15.020 10048 370013
14:00:16.123 10048 370014
14:00:16.790 10048 370014
ランニング:
$ txr data.txr data
MPID 10048 CPID 370007 Total time difference: 411 mili seconds
MPID 10048 CPID 370008 Total time difference: 299 mili seconds
MPID 10048 CPID 370009 Total time difference: 24 mili seconds
MPID 10048 CPID 370010 Total time difference: 133 mili seconds
MPID 10048 CPID 370012 Total time difference: 1027 mili seconds
MPID 10048 CPID 370014 Total time difference: 667 mili seconds
単一項目を表さず370011
、トリプル項目を表しません370013
。
パスワード:
@(do (defun mk-time-ms (date ms)
(let ((tsec (time-parse-utc "%H:%M:%S" date)))
(+ (* tsec 1000) ms))))
TIME MPID CPID
@(repeat)
@d0.@ms0 @mpid @cpid
@d1.@ms1 @mpid @cpid
@ (collect :gap 0)
@extra @mpid @cpid
@ (end)
@ (do (unless (boundp 'extra)
(let ((t0 (mk-time-ms d0 (toint ms0)))
(t1 (mk-time-ms d1 (toint ms1))))
(put-line `MPID @mpid CPID @cpid Total time difference: @(- t1 t0) mili seconds`))))
@(end)
mk-time-ms
日付を整数(Unix時代以降の時間)に解析し、それをミリ秒の値と組み合わせる関数。秒に1000を掛け、ミリ秒を加算します。
ヘッダー行をそのまま一致させます。
TIME MPID CPID
その後、@(repeat)
ゲームが始まります。同じcpid
(および)のmpid
2つの連続した行で始まる一連の行を探しています。追加することで、@(collect)
同じ行またはゼロ行以上にmpid
一致するゼロ行以上を追加しますcpid
。これらから時刻リストをextra
変数として収集します。各一致に対して、extra
変数がパターン一致にバインドされていない場合、これは正確に2行だけ一致し、追加項目はないことを意味します。この場合、時間差を計算し、所望の出力を生成します。
@(repeat)
一致する項目がない行をスキップすると、単一の項目が処理されます。繰り返しますが@(collect)
、基本的に一致しない行はスキップされるため、厳密にする必要があります:gap 0
。スペースは使用できません。それ以外の場合は、データ全体を消費し、@(repeat)
外部には何も残しません。
データに実際にトリプル冗長性がなく、ペアまたはシングルのみがある場合は、次のようになります。
@(do (defun mk-time-ms (date ms)
(let ((tsec (time-parse-utc "%H:%M:%S" date)))
(+ (* tsec 1000) ms))))
TIME MPID CPID
@(repeat)
@d0.@ms0 @mpid @cpid
@d1.@ms1 @mpid @cpid
@ (do (let ((t0 (mk-time-ms d0 (toint ms0)))
(t1 (mk-time-ms d1 (toint ms1))))
(put-line `MPID @mpid CPID @cpid Total time difference: @(- t1 t0) mili seconds`)))
@(end)
サンプルデータの場合、次の出力が含まれます。
MPID 10048 CPID 370013 Total time difference: 131 mili seconds
最初の2370013
行が比較され使用されます。以下は370013
シングルトンのように見え、スキップされます。これらの2つの違いを含めるには、@(trailer)
正しい場所に次の行を追加するなど、次のように変更します。
@(do (defun mk-time-ms (date ms)
(let ((tsec (time-parse-utc "%H:%M:%S" date)))
(+ (* tsec 1000) ms))))
TIME MPID CPID
@(repeat)
@d0.@ms0 @mpid @cpid
@ (trailer)
@d1.@ms1 @mpid @cpid
@ (do (let ((t0 (mk-time-ms d0 (toint ms0)))
(t1 (mk-time-ms d1 (toint ms1))))
(put-line `MPID @mpid CPID @cpid Total time difference: @(- t1 t0) mili seconds`)))
@(end)
次の行が出力に表示されます。
MPID 10048 CPID 370013 Total time difference: 131 mili seconds
MPID 10048 CPID 370013 Total time difference: 700 mili seconds
最初と2番目、2番目と3番目370013
の違いです。
@(trailer)
後続の内容は末尾のコンテキストという意味です。つまり、一致するが消費されません。したがって、@(repeat)
2つの行が一致しても1行だけが消費されるため、@(repeat)
2行が一致し、時間差が発生しても、次の反復が1行前に移動します。