次の形式の3列データがあります。
TIME MPID CPID
16:45:51 10051 77845
16:45:51 10051 77845
16:46:52 10051 77846
16:46:53 10051 77846
16:48:38 10051 77847
16:48:38 10051 77847
16:48:39 10051 77995
16:49:31 10051 77848
16:49:31 10051 77848
16:51:03 10051 77849
16:51:03 10051 77849
ここで、TIME列はHH:MM:SS形式のタイムスタンプで構成されています。 MPID および CPID 列は識別番号です。その意味は私の質問にとって重要ではありません。 MPID値もデータセットに存在し、出力に伝播する必要があることを除いては機能しません。
私が望むのは、CPID値が一致する行のペアを識別し、その時間の差を計算することです。たとえば、上記の例には、CPIDが77846の2行(3行目と4行目)があります。その時間は16:46:52と16:46:53なので、違いを計算したいです。
16:46:53 - 16:46:52 = 00:00:01
また、この結果を次の形式で出力したいと思います。
MPID 10051 CPID 77846 Total time difference: 01 seconds
与えられたCPIDがデータセットに正確に2回表示されない場合は、それを無視したいと思います。
サンプルデータが与えられた場合、希望の出力は次のようになります。
MPID 10051 CPID 77845 Total time difference: 00 seconds
MPID 10051 CPID 77846 Total time difference: 01 seconds
MPID 10051 CPID 77847 Total time difference: 00 seconds
MPID 10051 CPID 77848 Total time difference: 00 seconds
MPID 10051 CPID 77849 Total time difference: 00 seconds
答え1
仮説入力する
uniq -D
すべての重複行を表示するために使用される差分ファイル。3番目の場所フィールドただ、タイトルも削除されます。次に、date
フォーマットを使用して%s
時間を秒に変換して減算します。残りは標準ですシェル:uniq -D -f 2 input | 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: 01 seconds MPID 10051 CPID 77847 Total time difference: 00 seconds MPID 10051 CPID 77848 Total time difference: 00 seconds MPID 10051 CPID 77849 Total time difference: 00 seconds
以前の仕様(基準:OPコメント)、より多くのコードが必要です:
uniq -D -f 2 input | while read a b c && read d e f ; do g=$(( $(date -d $d +%s) - $(date -d $a +%s) )) printf "For %s %s time difference: %02i:%02i:%02i\n" \ $b $c $((g/360)) $(((g/60)%60)) $((g%60)) done
出力:
For 10051 77845 time difference: 00:00:00 For 10051 77846 time difference: 00:00:01 For 10051 77847 time difference: 00:00:00 For 10051 77848 time difference: 00:00:00 For 10051 77849 time difference: 00:00:00
答え2
目的のタスクを実行するおおよそのシェルスクリプトは次のとおりです。
#!/bin/bash
# pairwise_pid_time_diff.sh
# Write the data to a temporary file, sorted first by pid and then by time
cat "${1}" | sed 's/\s\+/ /g' | sort -k3,3 -k1,1 -n > sorted_pids.csv
# Compute the pair-wise time differences
for pid in $(cat sorted_pids.csv | cut -d' ' -f3 | uniq); do
if (( "$(grep "${pid}" sorted_pids.csv | wc -l)" == 2 )); then
time1_string="$(cat sorted_pids.csv | grep "${pid}" | head -1 | cut -d' ' -f1)"
time2_string="$(cat sorted_pids.csv | grep "${pid}" | tail -1 | cut -d' ' -f1)"
time1_seconds="$(date -u -d "${time1_string}" +"%s")"
time2_seconds="$(date -u -d "${time2_string}" +"%s")"
date -u -d "0 ${time2_seconds} sec - ${time1_seconds} sec" +"%H:%M:%S"
fi
done
# Delete the temporary file
rm sorted_pids.csv
これをテストするために、サンプルデータをファイルに書き込みます。
cat <<HEREDOC > pids.csv
16:45:51 10051 77845
16:45:51 10051 77845
16:46:52 10051 77846
16:46:53 10051 77846
16:48:38 10051 77847
16:48:38 10051 77847
16:48:39 10051 77995
16:49:31 10051 77848
16:49:31 10051 77848
16:51:03 10051 77849
16:51:03 10051 77849
HEREDOC
次にスクリプトを実行します。
bash pairwise_pid_time_diff.sh pids.csv
これにより、次のような結果が得られます。
00:00:00
00:00:01
00:00:00
00:00:00
00:00:00
スクリプトの実行に問題があると思われるので、以下はデバッグ目的のための別のバージョンです。
#!/bin/bash
# pairwise_pid_time_diff_debug.sh
# Write the data to a temporary file, sorted first by pid and then by time
1>&2 echo "Writing sorted data to temporary file."
cat "${1}" | sed 's/\s\+/ /g' | sort -k3,3 -k1,1 -n > sorted_pids.csv
# Compute the pair-wise time differences
1>&2 echo "Entering main loop..."
for pid in $(cat sorted_pids.csv | cut -d' ' -f3 | uniq); do
1>&2 echo "Looking at pid: ${pid}"
if (( "$(grep "${pid}" sorted_pids.csv | wc -l)" == 2 )); then
1>&2 echo "Found matching pair."
time1_string="$(cat sorted_pids.csv | grep "${pid}" | head -1 | cut -d' ' -f1)"
1>&2 echo "Time 1 string: ${time1_string}"
time2_string="$(cat sorted_pids.csv | grep "${pid}" | tail -1 | cut -d' ' -f1)"
1>&2 echo "Time 2 string: ${time2_string}"
time1_seconds="$(date -u -d "${time1_string}" +"%s")"
1>&2 echo "Time 1 in seconds: ${time1_seconds}"
time2_seconds="$(date -u -d "${time2_string}" +"%s")"
1>&2 echo "Time 1 in seconds: ${time2_seconds}"
time_difference="$(date -u -d "0 ${time2_seconds} sec - ${time1_seconds} sec" +"%H:%M:%S")"
echo "${time_difference}"
fi
done
# Delete the temporary file
rm sorted_pids.csv
1>&2 echo "Deleted temporary file."
このスクリプトを実行すると、次の結果が表示されます。
bash pairwise_pid_time_diff_debug.sh pids.csv
Writing sorted data to temporary file.
Entering main loop...
Looking at pid: 77845
Found matching pair.
Time 1 string: 16:45:51
Time 2 string: 16:45:51
Time 1 in seconds: 1510332351
Time 1 in seconds: 1510332351
00:00:00
Looking at pid: 77846
Found matching pair.
Time 1 string: 16:46:52
Time 2 string: 16:46:53
Time 1 in seconds: 1510332412
Time 1 in seconds: 1510332413
00:00:01
Looking at pid: 77847
Found matching pair.
Time 1 string: 16:48:38
Time 2 string: 16:48:38
Time 1 in seconds: 1510332518
Time 1 in seconds: 1510332518
00:00:00
Looking at pid: 77995
Looking at pid: 77848
Found matching pair.
Time 1 string: 16:49:31
Time 2 string: 16:49:31
Time 1 in seconds: 1510332571
Time 1 in seconds: 1510332571
00:00:00
Looking at pid: 77849
Found matching pair.
Time 1 string: 16:51:03
Time 2 string: 16:51:03
Time 1 in seconds: 1510332663
Time 1 in seconds: 1510332663
00:00:00
Deleted temporary file.
スクリプトを実行する代わりに、手動でプロセスを段階的に進めましょう。まず、データファイルを作成しましょう。
cat <<HEREDOC > pids.csv
16:45:51 10051 77845
16:45:51 10051 77845
16:46:52 10051 77846
16:46:53 10051 77846
16:48:38 10051 77847
16:48:38 10051 77847
16:48:39 10051 77995
16:49:31 10051 77848
16:49:31 10051 77848
16:51:03 10051 77849
16:51:03 10051 77849
HEREDOC
次に、データを最初にPIDでソートしてから、時間でソートしてみましょう。
cat pids.csv | sed 's/\s\+/ /g' | sort -k3,3 -k1,1 -n > sorted_pids.csv
ファイルが正しく作成されたことを確認しましょう。
cat sorted_pids.csv
次のような結果が出てくるはずです。
16:45:51 10051 77845
16:45:51 10051 77845
16:46:52 10051 77846
16:46:53 10051 77846
16:48:38 10051 77847
16:48:38 10051 77847
16:49:31 10051 77848
16:49:31 10051 77848
16:51:03 10051 77849
16:51:03 10051 77849
16:48:39 10051 77995
それでは、データから一意のPIDを取得します。
user@host:~$ cat sorted_pids.csv | cut -d' ' -f3 | uniq
77845
77846
77847
77848
77849
77995
最初のPID:77845の時差を計算してみましょう。
まず、77845の最初の時間文字列を取得します。
time1_string="$(cat sorted_pids.csv | grep 77845 | head -1 | cut -d' ' -f1)"
私たちの値が正しいことを確認してみましょう:
user@host:~$ echo ${time1_string}
16:45:51
それでは、これを秒に変換してみましょう。
time1_seconds="$(date -u -d "${time1_string}" +"%s")"
そして、我々が得た値を確認してください。
user@host:~$ echo ${time1_seconds}
1510332351
それでは、2番目に文字列を使用して同じことをしましょう。
time2_string="$(cat sorted_pids.csv | grep 77845 | tail -1 | cut -d' ' -f1)"
time2_seconds="$(date -u -d "${time2_string}" +"%s")"
user@host:~$ echo "${time2_string}"
16:45:51
user@host:~$ echo "${time2_seconds}"
1510332351
次に、差を秒単位で計算し、それをビート記号に変換します。
difference=$(date -u -d "0 ${time2_seconds} sec - ${time1_seconds} sec" +"%H:%M:%S")
結果を確認してください。
00:00:00