Linux cmd를 사용하여 열을 기반으로 uniq 행만 가져오는 방법은 무엇입니까?

Linux cmd를 사용하여 열을 기반으로 uniq 행만 가져오는 방법은 무엇입니까?

내 데이터 세트는 다음과 같습니다.

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관련 행이 모두 삭제됩니다.

sortLinux 나 uniq다른 것을 사용하여 문제를 해결할 수 있습니까 ?

답변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/dataPerl one-liner로 수행할 수 있다고 가정합니다.

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유일한 솔루션

  1. 질서를 지키지 않음

    awk -F, 'NR>1 { count[$1]++ ; line[$1]=$0 ;} 
       END { for ( c in count) if (count[c] ==1) print line[c]}' data
    
  2. 질서 유지

    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]인쇄 라인

  • acol[]변형을 보존하기 위해 라인 순서를 저장하는 데 사용됩니다 .

이것은 한 줄로 작성할 수 있습니다. 가독성을 위해 접습니다.

답변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

관련 정보