위 셀의 숫자보다 1이 더 큰 숫자가 포함된 경우 스프레드시트의 특정 행을 다른 파일로 출력하고 싶습니다.

위 셀의 숫자보다 1이 더 큰 숫자가 포함된 경우 스프레드시트의 특정 행을 다른 파일로 출력하고 싶습니다.

다음과 같은 큰 CSV 파일이 있습니다.

SomeData,SomeData,1,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,2,SomeData  
SomeData,SomeData,3,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,2,SomeData  
SomeData,SomeData,3,SomeData  
SomeData,SomeData,4,SomeData  
SomeData,SomeData,5,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,1,SomeData  
SomeData,SomeData,1,SomeData  

세 번째 값이 세트의 일부인 행만 포함하는 새 csv 파일을 만들고 싶습니다. 즉, 아래 행의 세 번째 필드에서 더 높은 값이 있으면 두 행을 모두 포함하고 싶습니다.

따라서 위 예에서는 2-4행과 8-12행만 새 파일에 저장하려고 합니다.

grep이 패턴을 찾는 방법을 찾으려고 노력 중입니다 .

어떤 아이디어가 있나요?

감사해요

답변1

CSV 파일은 까다롭습니다. 쉼표를 포함할 수 있는 적절하게 인용된 데이터 필드를 가정하면 Somedata구분 기호를 탭 문자(대부분의 최신 셸에서)와 같이 데이터에 절대 나타나지 않는 것으로 바꿀 수 있습니다 $'\t'(작동하는 내용으로 변경할 수 있음). . 데이터 필드에 쉼표가 없으면 csvformat여기의 비트를 건너뜁니다.

사용csvkit:

$ csvformat -D$'\t' data.csv
SomeData        SomeData        1       SomeData
SomeData        SomeData        1       SomeData
SomeData        SomeData        2       SomeData
SomeData        SomeData        3       SomeData
SomeData        SomeData        1       SomeData
etc.

그런 다음 이를 awk그룹을 찾는 실제 작업을 수행하는 스크립트에 전달할 수 있습니다.

NR > 1 && $3  == count + 1 {
    # This line is part of the set.

    ++count;        # We expect this value on the next line.
    ++set_size;     # This is the number of lines in the set.

    # Output previous line and remember this line.
    print previous_line;
    previous_line = $0;

    # Continue with next line.
    next;
}

set_size > 0 && $3 != count + 1 {
    # This line is not part of the set, but we're currently tracking a
    # set.  This means that the set ended, so output the last line of
    # the set.

    print previous_line;
    set_size = 0;
}

{
    # This line might be part of the next set.

    count = $3;
    previous_line = $0
}

실행하세요:

$ csvformat -D$'\t' data.csv | awk -F$'\t' -f script.awk
SomeData        SomeData        1       SomeData
SomeData        SomeData        2       SomeData
SomeData        SomeData        3       SomeData
SomeData        SomeData        1       SomeData
SomeData        SomeData        2       SomeData
SomeData        SomeData        3       SomeData
SomeData        SomeData        4       SomeData
SomeData        SomeData        5       SomeData

그런 다음 표준 쉼표로 구분된 형식으로 되돌립니다.

$ csvformat -D$'\t' data.csv | awk -F$'\t' -f script.awk | csvformat -d$'\t'
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,4,SomeData
SomeData,SomeData,5,SomeData

데이터 필드 내부의 데이터에 쉼표가 없으면 csvformat완전히 생략할 수 있습니다.

$ awk -F',' -f script.awk data.csv
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,4,SomeData
SomeData,SomeData,5,SomeData

답변2

데이터가 이 처리에 datafile사용 가능한 파일에 있다고 가정합니다 . ( 한 줄 문맥만 처리하기 때문에 awk사용할 수 없습니다 .)grep

awk -F, '
    # Initially we are not in a block
    BEGIN { inblock=0 }

    # If the third field is greater than that on the previous line, print
    # it. But if we were not already in a block then print the saved line
    # too - and mark that we are now in a block
    NR>1 && $3>third { if (!inblock) { print line; inblock=1 } print $0 }

    # If we are in a block and the third field is smaller that the previous
    # line value, drop out of the block
    inblock && $3<=third { inblock=0 }

    # Save the values each time around
    {third=$3; line=$0 }
' datafile
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,1,SomeData
SomeData,SomeData,2,SomeData
SomeData,SomeData,3,SomeData
SomeData,SomeData,4,SomeData
SomeData,SomeData,5,SomeData

관련 정보