타임스탬프 열을 기준으로 날짜 및 시간 열 병합 및 추가

타임스탬프 열을 기준으로 날짜 및 시간 열 병합 및 추가

다음과 같은 샘플 데이터 항목이 포함된 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

내가하고 싶은 것은 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

그러나 이 두 개의 새 필드가 현재 입력 행에 추가되기를 원한다고도 말씀하셨습니다. 이는 각 행에서 반복되는 날짜와 시간으로 끝나기 때문에 나에게는 별로 의미가 없습니다(이미 타임스탬프 필드의 각 행의 시작 부분에 있음).

다음은 정확히 귀하가 요청한 내용은 아니지만 제 생각에는 개선된 내용입니다.

각 행의 끝에 날짜와 시간을 추가하는 대신 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필드를 건너뛸 수 있지만 공백만 필드 구분 기호로 인식되고 쉼표나 처음 두 필드만 인식되지 않음). 그것이 당신이 원하는 것이라면 그대로 작동할 것입니다.

그렇지 않으면 고유성을 확인하는 대신 awkor 또는 무언가를 사용해야 합니다 . 예를 들어 다음은 쉼표로 구분된 처음 두 개의 필드(예: 날짜 및 시간)만 비교합니다.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

관련 정보