データテーブル内の一致するレコード間のペアごとの時間差を計算します。

データテーブル内の一致するレコード間のペアごとの時間差を計算します。

次の形式の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

  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
    
  2. 以前の仕様(基準: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

関連情報