타임스탬프 열을 기반으로 날짜 및 시간 열을 통합하고 추가합니다.

타임스탬프 열을 기반으로 날짜 및 시간 열을 통합하고 추가합니다.

다음과 같은 샘플 데이터 항목이 포함된 csv 파일이 있습니다.

Timestamp,data1,data2
2018 07 16 13:00:00,23,45
2018 07 16 13:10:00,23,45
2018 07 16 13:20:00,23,45
2018 07 16 13:30:00,23,45
2018 07 16 13:50:00,23,45
2018 07 16 14:20:00,23,45
2018 07 16 14:40:00,23,45
2018 07 16 14:50:00,23,45
2018 07 16 15:10:00,23,45
2018 07 16 17:50:00,23,45
2018 07 16 18:10:00,23,45
2018 07 17 10:10:00,23,45
2018 07 18 13:20:00,23,45
2018 07 19 13:30:00,23,45

내가하고 싶은 것은 다른 2 개의 열 Date& 을 만드는 것입니다 Hour. 열에 Date는 날짜가 포함되고, Hour열에는 데이터가 캡처된 모든 시간이 포함됩니다. 예를 들어, 위의 데이터를 기반으로 다음과 같은 출력을 원합니다(동일 파일에 열 2개만 추가).

Date,Hour
2018 07 16,13
2018 07 16,14
2018 07 16,15
2018 07 16,17
2018 07 16,18
2018 07 17,10
2018 07 18,13
2018 07 19,13

예를 들어 2018년 7월 16일 13시(1시 또는 다수)에 항목이 있는 경우 해당 날짜와 13시를 한 번만 나열하고 날짜가 변경될 때까지 다른 시간의 항목으로 이동합니다. 그리고 프로세스가 반복됩니다.

파일에는 며칠 동안 많은 항목(100000개 이상)이 있으며 위와 같이 한 시간에 캡처된 데이터의 수는 다양합니다. 이 문제를 해결하려면 어떻게 해야 합니까? 내 설명이 충분히 명확하기를 바랍니다.

답변1

사용 awk:

awk 'BEGIN{ OFS=FS="," }
  NR==1{ print "Date", "Hour"; next }
  {
    $0=substr($1, 1, 10) FS substr($1, 12, 2)
    if ($0 == prev) next  # skip to next record if record equals prev
    prev=$0               # remember record
  }
  1                       # print record
' file

따라서 날짜 문자열은 첫 번째 필드의 위치 1에서 시작하는 처음 10자로 구성되며, 시간은 위치 12에서 시작하는 2개의 문자에서 추출됩니다.

두 값과 필드 구분 기호( FS)가 모두 레코드( $0)에 할당되고 이전에 기억된 레코드가 다른 경우 인쇄됩니다.

답변2

sortuniq귀하의 질문에 표시된 출력 예제를 제공할 수 있습니다 .

$ sed -e 's/Timestamp.*/Date,Hour/; s/ \(..\):.*/,\1/' file.csv  | uniq
Date,Hour
2018 07 16,13
2018 07 16,14
2018 07 16,15
2018 07 16,17
2018 07 16,18
2018 07 17,10
2018 07 18,13
2018 07 19,13

그러나 현재 입력 라인에 이 두 개의 새 필드를 추가하고 싶다고도 말씀하셨습니다. 그렇게 하면 각 줄에 날짜와 시간이 중복되게 되므로(이미 타임스탬프 필드의 각 줄 시작 부분에 있음) 나에게는 별로 의미가 없습니다.

다음은 정확히 귀하가 요청한 내용은 아니지만 IMO의 개선 사항입니다.

각 줄 끝에 날짜 및 시간을 추가하는 대신 sed기존 타임스탬프 필드를 날짜 및 시간 필드로 변환하는 데 사용됩니다. 그런 다음 uniq중복된 줄을 제거하는 데 사용됩니다.

$ sed -e 's/Timestamp/Date,Hour/; s/ \(..\):[^,]*,/,\1,/' file.csv  | uniq
Date,Hour,data1,data2
2018 07 16,13,23,45
2018 07 16,14,23,45
2018 07 16,15,23,45
2018 07 16,17,23,45
2018 07 16,18,23,45
2018 07 17,10,23,45
2018 07 18,13,23,45
2018 07 19,13,23,45

이는 입력 파일이 이미 타임스탬프 순서로 되어 있다고 가정합니다.

참고: data1또는 값이 data2다를 수 있는 경우 출력 라인은 고유하지 않으며 해당 라인이 인쇄됩니다. 이는 uniq전체 줄을 이전 줄과 비교하기 때문입니다( uniq필드를 건너뛰도록 만들 수 있지만 공백만 필드 구분 기호로 인식하고 쉼표를 사용하도록 만들 수 없고 처음 두 필드만 사용하도록 만들 수 없습니다). . 그것이 당신이 원하는 것이라면 그대로 작동할 것입니다.

그렇지 않으면 고유성을 확인하는 대신 awk또는 등을 사용해야 합니다 . 예를 들어 다음은 쉼표로 구분된 처음 두 개의 필드(예: 날짜 및 시간)만 비교하는 데 사용됩니다.perluniqawk

$ sed -e 's/Timestamp/Date,Hour/; s/ \(..\):[^,]*,/,\1,/' file.csv  |
    awk -F, 'prev != $1$2 {print; prev=$1$2}'

sed그러나 출력 을 로 파이프하려는 경우 awk가 수행할 수 있는 모든 작업을 수행할 수 있으므로 단독으로 awk사용하는 것이 좋습니다. 이것이 바로 awk의 , 및 함수의 목적입니다. 예를 들어awksedsub()gsub()gensub()

$ awk -F, -v OFS=, '{ sub(/Timestamp/,"Date,Hour");
                       $1 = gensub(/ ([0-9]+):.*/,",\\1",1,$1)
                    };
                    prev != $1$2 {print; prev=$1$2}' file.csv

또는 다음과 같이 perl:

$ perl -lne 's/Timestamp/Date,Hour/;
             s/ (\d\d):.*?,/,$1,/;
             ($current) = (m/^[^,]+,\d\d|^Date),/);
             if ($prev ne $current) {print ; $prev = $current}' file.csv

관련 정보