이것은 내 데이터 세트입니다.
col1,col2,col3
a,b,c
a,d,f
d,u,v
f,g,h
d,u,g
x,t,k
예상 출력:
f,g,h
x,t,k
선택 기준:
어떤 일이 여러 번 발생하면 col1
관련된 모든 행이 삭제됩니다.
sort
uniq
Linux나 다른 방법을 사용하여 이 문제를 해결할 수 있나요 ?
답변1
이는 "버퍼되지 않은" (1) 2단계 방법 입니다 awk
(일반 파일에만 해당).
awk -F',' 'NR==FNR{cnt[$1]++;next} FNR>1&&cnt[$1]==1' input.csv input.csv
이렇게 하면 파일이 두 번 처리되므로 명령줄에서 매개변수로 두 번 선언합니다.
- 이 매개변수는
-F','
필드 구분 기호를 로 설정합니다,
. - 첫 번째 단계에서
NR
전역 행 카운터가FNR
파일별 행 카운터와 같을 때 열 1의 각 값이 배열에서 발견되는 빈도를 기록하지만cnt
(해당 값을 "배열 인덱스"로 사용) 즉시 처리로 이동합니다. 다음 줄. - 두 번째 패스에서는 첫 번째 열의 현재 값의 발생 카운터가 정확히 1인지, 파일의 줄 번호가 1보다 큰지(헤더를 건너뛰기 위해) 확인합니다. 이것이 참인 경우에만 현재 행이 인쇄됩니다. 이는 현재 행을 인쇄하도록 지시
awk
하는 규칙 블록 외부의 표현식 구문을 활용합니다.true
awk
(1) 내 댓글에 대한 답변버퍼링되지 않은솔루션은 파일의 일부 데이터를 일시적으로 RAM에 저장하므로 따옴표로 묶습니다.하다RAM 사용량이 함께 제공됩니다. 하지만 파일 내용을 그대로 저장하지는 않습니다.또한RAM에 있는 다른 스크롤 유지 데이터(여기서나실용적인 의미에서 "버퍼링"을 고려할 것입니다.)
답변2
파일이 /tmp/data
Perl 한 줄로 수행할 수 있는 작업이라고 가정합니다.
perl -e 'while(<STDIN>) { /(^\S+?),/; $show->{$1}=$_; $count->{$1}++;}; foreach(keys %$show) {print $show->{$_} if($count->{$_} == 1);}' < /tmp/data
또는 더 읽기 쉽게 하려면...:
while(<STDIN>) { #loop through all lines in the input and put the lines in "$_"
/(^\S+?),/; #Everything before the first "," now ends up in "$1"
$show->{$1} = $_; #a hash will be created with as keys the "$1" and as values the "$_"
$count->{$1}++; #In the hash $count the number of occurrences will be increased everytime the same $1 appears
}
foreach(keys %$show) { #loop trough all lines
print $show->{$_} if($count->{$_} == 1); #only print them if they occur once
}
답변3
awk
유일한 해결책
명령에 불복종하다
awk -F, 'NR>1 { count[$1]++ ; line[$1]=$0 ;} END { for ( c in count) if (count[c] ==1) print line[c]}' data
질서 유지
awk -F, 'NR>1 { row[a]=$0; col[a]=$1; count[$1]++; ++a; } END { for (i=0; i<a; ++i) if (count[col[i]]==1) print row[i]; }' data
어디
-F,
,
awk에게 구분 기호 로 사용하도록 지시NR>1
첫 번째 줄 이후count[$1]++
첫 번째 열의 요소 개수 계산line[$1]=$0
매장 라인END
파일이 끝난 후for ( c in count)
요소 반복if (count[c] ==1)
하나만 있다면print line[c]
인쇄 라인a
col[]
변형의 행 순서를 보존하는 순서를 저장하는 것입니다 .
한 줄이면 됩니다. 가독성을 위해 접었습니다.
답변4
필수 POSIX 도구의 모든 버전을 사용하고 입력의 모든 문자를 장식/정렬/사용/장식 취소합니다(입력이 실제로 쉼표 및/또는 줄 바꿈을 포함할 수 있는 인용 필드가 있는 CSV가 아닌 한, 다른 모든 답변도 실패함) 출력의 입력 줄 순서를 유지하고 입력을 한 번만 엽니다. 따라서 입력이 파이프나 파일에서 나오고 전체 입력을 메모리에 저장하지 않는 경우 작동합니다.
$ awk 'BEGIN{FS=OFS=","} NR>1{print ++cnt[$1], NR, $0}' file |
sort -nt, -k1,1r -k2,2 |
awk -F, '(!seen[$3]++) && ($1==1)' |
cut -d, -f3-
f,g,h
x,t,k