Remova a linha inteira de um arquivo se a primeira coluna for repetida

Remova a linha inteira de um arquivo se a primeira coluna for repetida

Tenho um arquivo contendo duas colunas e 10 milhões de linhas. A primeira coluna contém muitos valores repetidos, mas há um valor distinto na coluna 2. Quero remover as linhas repetidas e manter apenas uma usando awk. Nota: o arquivo é classificado com valores na coluna 1. Por exemplo:

1.123 -4.0
2.234 -3.5
2.234 -3.1
2.234 -2.0
4.432 0.0
5.123 +0.2
8.654 +0.5
8.654 +0.8
8.654 +0.9
.
.
.
.

Resultado esperado

1.123 -4.0
2.234 -3.5
4.432 0.0
5.123 +0.2
8.654 +0.5
.
.
.
.

Responder1

Algumas maneiras:

  1. estranho

    awk '!a[$1]++' file
    

    Esta é uma maneira muito condensada de escrever isso:

    awk '{if(! a[$1]){print; a[$1]++}}' file
    

    Portanto, se o primeiro campo atual ( $1) não estiver no aarray, imprima a linha e adicione o primeiro campo a a. Da próxima vez que vermos esse campo, ele estará no array e, portanto, não será impresso.

  2. Perl

    perl -ane '$k{$F[0]}++ or print' file
    

    ou

    perl -ane 'print if !$k{$F[0]}++' file
    

    Este é basicamente o mesmo que awkaquele. Isso -nfaz com que o Perl leia o arquivo de entrada linha por linha e aplique o script fornecido por -ea cada linha. O -airá dividir automaticamente cada linha em espaços em branco e salvar os campos resultantes na @Fmatriz. Por fim, o primeiro campo é adicionado ao %khash e caso ainda não esteja lá, a linha é impressa. A mesma coisa poderia ser escrita como

    perl -e 'while(<>){
                @F=split(/\s+/); 
                print unless defined($k{$F[0]}); 
                $k{$F[0]}++;
             }' file
    
  3. Coreutils

    rev file | uniq -f 1 | rev
    

    Este método funciona primeiro invertendo as linhas filede modo que se uma linha for 12 345 agora será 543 21. Em seguida, ignoramos uniq -f 1o primeiro campo, ou seja, a coluna em que 543 está. file. Usar uniqaqui tem o efeito de filtrar quaisquer linhas duplicadas, mantendo apenas 1 de cada. Por último, colocamos as linhas de volta na ordem original com outro reverso.

  4. Classificação GNU (comosugeridopor @StéphaneChazelas)

    sort -buk1,1
    

    O -bsinalizador ignora os espaços em branco iniciais e os -umeios imprimem apenas campos exclusivos. A parte inteligente é o -k1,1. O -ksinalizador define o campo para classificação. Ele assume o formato geral, -k POS1[,POS2]o que significa apenas olhar os campos POS1por meio do POS2 durante a classificação. Então, -k1,1significa olhar apenas para o primeiro campo. Dependendo dos seus dados, você também pode querer adicionar uma destas opções:

     -g, --general-numeric-sort
          compare according to general numerical value
     -n, --numeric-sort
          compare according to string numerical value
    

Responder2

Se a primeira coluna tiver sempre 5 caracteres, você pode simplesmente usar uniq:

uniq -w 5 file

Se não, use awk:

awk '$1!=a{print $0; a=$1}' file

O primeiro seria definitivamente mais rápido com um arquivo enorme.

informação relacionada