데이터 테이블에서 일치하는 레코드 간의 쌍별 시간 차이(밀리초)를 계산합니다.

데이터 테이블에서 일치하는 레코드 간의 쌍별 시간 차이(밀리초)를 계산합니다.

다음 형식의 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인 두 개의 행(세 번째 및 네 번째 행)이 있습니다. 해당 시간은 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가 데이터 세트에 정확히 두 번 나타나지 않으면 이를 무시하고 싶습니다.

샘플 데이터가 주어진 경우 원하는 출력은 다음과 같아야 합니다.

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

세 개의 동일한 행을 추가하여 해당 행이 거부되었음을 표시하고 "정확히 두 번" 요구 사항을 충족하여 CPID샘플 데이터를 조정했습니다 . 또한 우리가 원하는 쌍인 370013두 줄을 더 추가했습니다 .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두 개의 연속 라인으로 시작하는 일련의 라인을 찾고 있습니다 . 추가함으로써 @(collect)우리는 동일하거나 0개 이상의 행 mpid과 일치하는 0개 이상의 행을 추가합니다 cpid. 이들로부터 시간 목록을 extra변수로 수집합니다. 각 일치 항목에 대해 extra변수가 패턴 일치에 바인딩되지 않은 경우 이는 정확히 두 줄만 일치하고 추가 항목은 없음을 의미합니다. 이 경우 시간 차이를 계산하고 원하는 출력을 생성합니다.

@(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

처음 두 370013행이 비교되고 사용됩니다. 다음은 370013싱글톤처럼 보이며 건너뜁니다. 이러한 두 가지 차이점을 포함하려면 @(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

첫 번째와 두 번째 , 두 번째와 세 번째 370013의 차이입니다 .

@(trailer)뒤따르는 내용은 후행 컨텍스트라는 의미입니다. 즉, 일치하지만 소비되지는 않습니다. 따라서 @(repeat)두 행이 일치하더라도 이제 하나의 행만 소비하므로 @(repeat)두 행이 일치하고 시간 차이가 발생하더라도 다음 반복이 한 행 앞으로 이동하게 됩니다.

관련 정보