탭으로 구분된 텍스트 파일에서 중복된 값을 제거하는 방법

탭으로 구분된 텍스트 파일에서 중복된 값을 제거하는 방법

아래와 같이 탭으로 구분된 열 텍스트가 있습니다.

A      B1      B1     C1
B      B2      D2 
C      C12     C13    C13
D      D3      D5      D9
G      F2      F2   

위의 표를 아래와 같이 변환하려면 어떻게 해야 합니까?

A      B1     C1
B      B2     D2 
C      C12    C13
D      D3     D5     D9
G      F2   

실제 데이터 파일을 추출했습니다. 탭으로 구분된 파일입니다. 귀하(Stéphane Chazelas?)가 게시한 명령줄을 시도해 보았지만 제대로 작동하지만 마지막 열의 중복 항목을 제거할 수 없습니다.

A  CD274    PDCD1LG2  CD276   PDCD1LG2  CD274
B  NEK2     NEK6      NEK10   NEK10     NEKL-4
C  TNFAIP3  OTUD7B    OTUD7B  TNFAIP3   TNFAIP3
D  DUSP16   DUSP4     DUSP8   VHP-1     DUSP8
E  AGO2     AGO2      AGO2    AGO2      AGO2

출력은 다음과 같아야합니다

A  CD274    CD276   PDCD1LG2
B  NEK2     NEK6    NEK10     NEKL-4
C  TNFAIP3  OTUD7B
D  DUSP16   DUSP4   DUSP8     VHP-1
E  AGO2

답변1

첫 번째 샘플 데이터 세트:

$ awk -vOFS='\t' '{ r=""; delete t; for (i=1;i<=NF;++i) { if (!t[$i]++) { r = r ? r OFS $i : $i } } print r }' file
A       B1      C1
B       B2      D2
C       C12     C13
D       D3      D5      D9
G       F2

두 번째 예제 데이터 세트(동일 awk스크립트):

$ awk -vOFS='\t' '{ r=""; delete t; for (i=1;i<=NF;++i) { if (!t[$i]++) { r = r ? r OFS $i : $i } } print r }' file
A       CD274   PDCD1LG2        CD276
B       NEK2    NEK6    NEK10   NEKL-4
C       TNFAIP3 OTUD7B
D       DUSP16  DUSP4   DUSP8   VHP-1
E       AGO2

스크립트는 입력 파일을 한 줄씩 읽고 file각 줄에 대해 각 필드를 반복하여 출력 줄을 작성합니다 r. 필드의 값이 출력 줄에 추가된 경우( t사용된 필드 값의 조회 테이블에 의해 결정됨) 이면 해당 필드가 무시되고, 그렇지 않으면 추가됩니다.

입력 행의 모든 ​​필드가 처리되면 구성된 행이 출력됩니다.

-vOFS='\t'출력 필드 구분 기호는 명령줄에서 탭으로 설정됩니다.


공개된 스크립트 awk:

{
    r = ""
    delete t

    for (i = 1; i <= NF; ++i) {
        if (!t[$i]++) {
            r = r ? r OFS $i : $i
        }
    }

    print r
}

답변2

sed/tr, uniq 및 붙여넣기

while read -r l; do sed 's/\t/\n/g' <<< "$l" | uniq | paste -s; done < test

또는 POSIX 호환:

while read -r l; do echo "$l" | tr '\t' '\n' | uniq | paste -s -; done < test

파일의 경우 모든 문자를 한 줄씩 개행 문자로 바꾸고, 중복 항목을 제거하고 개행 문자를 다시 문자로 바꾸기 위해 실행 test합니다 .TabuniqTab

$ cat test
A       B1      B1      C1
B       B2      D2
C       C12     C13     C13
D       D3      D5      D9
G       F2      F2

$ while read -r l; do sed 's/\t/\n/g' <<< "$l" | uniq | paste -s; done < test
A       B1      C1
B       B2      D2
C       C12     C13
D       D3      D5      D9
G       F2

알아채다: 이 솔루션은아니요여러 줄에 걸친 중복 작업에 사용됩니다 C1.

A       B1      B1      C1
C1      B       B2      D2

답변3

어쩌면 다음과 같은 것일 수도 있습니다.

gawk -vRS='\\s*\\S*' -vORS= '{$0=RT};$1!=prev;{prev=$1}'

RS=pattern...트릭을 사용하면 {$0=RT}패턴과 일치하는 부분으로 정의된 레코드를 처리할 수 있습니다.

따라서 여기서는 입력을 <whitespace><non-whitespace> $0레코드 로 자르고 (첫 번째이자 유일한 필드)를 <non-whitespace>입력합니다 . 이전 기록과 동일하지 않은 기록을 $1인쇄하고 있습니다 .$1

다음과 같이 입력하면:

A      B1      B1     C1
B      B2      D2 
C      C12     C13    C13
D      D3      D5      D9
G      F2      F2

기록은 다음과 같습니다

[A][ B1] [ B1] [ C1][
비][ B2][ D2][
C][ C12][ C13] [ C13] [
디][ D3][ D5][ D9][
G][ F2] [ F2] [
]

그러나 두 번째 예에서는 작동하지 않습니다. 일부 개행 문자가 제거될 수 있습니다.

답변4

그리고 perl:

각 줄에는 고유한 단어가 있습니다.

perl -MList::Util=uniq -lape '$_ = join "\t", uniq @F'

세상에서 유일한 단어:

perl -lape '$_ = join "\t", grep {!$count{$_}++} @F'

아니면 두 번째 줄부터 시작하는 각 단어 줄을 고려해 보세요 .

perl -lape '$_ = join "\t", shift(@F), grep {!$count{$_}++} @F'

관련 정보