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:
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 noa
array, imprima a linha e adicione o primeiro campo aa
. Da próxima vez que vermos esse campo, ele estará no array e, portanto, não será impresso.Perl
perl -ane '$k{$F[0]}++ or print' file
ou
perl -ane 'print if !$k{$F[0]}++' file
Este é basicamente o mesmo que
awk
aquele. Isso-n
faz com que o Perl leia o arquivo de entrada linha por linha e aplique o script fornecido por-e
a cada linha. O-a
irá dividir automaticamente cada linha em espaços em branco e salvar os campos resultantes na@F
matriz. Por fim, o primeiro campo é adicionado ao%k
hash e caso ainda não esteja lá, a linha é impressa. A mesma coisa poderia ser escrita comoperl -e 'while(<>){ @F=split(/\s+/); print unless defined($k{$F[0]}); $k{$F[0]}++; }' file
Coreutils
rev file | uniq -f 1 | rev
Este método funciona primeiro invertendo as linhas
file
de modo que se uma linha for 12 345 agora será 543 21. Em seguida, ignoramosuniq -f 1
o primeiro campo, ou seja, a coluna em que 543 está.file
. Usaruniq
aqui 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.Classificação GNU (comosugeridopor @StéphaneChazelas)
sort -buk1,1
O
-b
sinalizador ignora os espaços em branco iniciais e os-u
meios imprimem apenas campos exclusivos. A parte inteligente é o-k1,1
. O-k
sinalizador define o campo para classificação. Ele assume o formato geral,-k POS1[,POS2]
o que significa apenas olhar os camposPOS1
por meio do POS2 durante a classificação. Então,-k1,1
significa 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.