![데이터 테이블에서 일치하는 레코드 간의 쌍별 시간 차이를 계산합니다.](https://linux55.com/image/121439/%EB%8D%B0%EC%9D%B4%ED%84%B0%20%ED%85%8C%EC%9D%B4%EB%B8%94%EC%97%90%EC%84%9C%20%EC%9D%BC%EC%B9%98%ED%95%98%EB%8A%94%20%EB%A0%88%EC%BD%94%EB%93%9C%20%EA%B0%84%EC%9D%98%20%EC%8C%8D%EB%B3%84%20%EC%8B%9C%EA%B0%84%20%EC%B0%A8%EC%9D%B4%EB%A5%BC%20%EA%B3%84%EC%82%B0%ED%95%A9%EB%8B%88%EB%8B%A4..png)
다음 형식의 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인 두 개의 행(세 번째 및 네 번째 행)이 있습니다. 해당 시간은 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가 데이터 세트에 정확히 두 번 나타나지 않으면 이를 무시하고 싶습니다.
샘플 데이터가 주어진 경우 원하는 출력은 다음과 같아야 합니다.
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
모든 중복 라인을 표시 하는 데 사용되는 차등 파일입니다.세 번째 장소필드오직, 제목도 제거됩니다. 그런 다음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
이제 두 번째로 문자열을 사용하여 동일한 작업을 수행해 보겠습니다.
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