다음과 같은 큰 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