Encontre linhas duplicadas em um arquivo e conte quantas vezes cada linha foi duplicada?


529

Suponha que eu tenha um arquivo semelhante ao seguinte:

123 
123 
234 
234 
123 
345

Gostaria de descobrir quantas vezes '123' foi duplicado, quantas vezes '234' foi duplicado, etc. Então, idealmente, a saída seria como:

123  3 
234  2 
345  1

4
Qual idioma você quer usar?
VMAtm

Respostas:


791

Supondo que haja um número por linha:

sort <file> | uniq -c

Você pode usar o --countsinalizador mais detalhado também com a versão GNU, por exemplo, no Linux:

sort <file> | uniq --count

3
Isto é o que eu faço, no entanto, algoritmicamente, isso não parece ser a abordagem mais eficiente (O (n log n) * avg_line_len onde n é o número de linhas). Estou trabalhando em arquivos com vários gigabytes de tamanho, portanto o desempenho é uma questão fundamental. Gostaria de saber se existe uma ferramenta que faça apenas a contagem em uma única passagem usando uma árvore de prefixos (no meu caso, as strings costumam ter prefixos comuns) ou similares, que devem funcionar em O (n) * avg_line_len. Alguém conhece essa ferramenta de linha de comando?
Droggl

21
Uma etapa adicional é canalizar a saída disso para um comando final 'sort -n'. Isso ordenará os resultados pelos quais as linhas ocorrem com mais frequência.
samoz

79
Se você quiser imprimir apenas linhas duplicadas, use 'uniq -d'
DmitrySandalov

6
Se você quiser classificar novamente o resultado, poderá usar sortnovamente como:sort <file> | uniq -c | sort -n
Abhishek Kashyap

413

Isso imprimirá apenas linhas duplicadas , com contagens:

sort FILE | uniq -cd

ou, com as opções longas do GNU (no Linux):

sort FILE | uniq --count --repeated

no BSD e OSX, você deve usar o grep para filtrar linhas exclusivas:

sort FILE | uniq -c | grep -v '^ *1 '

Para o exemplo dado, o resultado seria:

  3 123
  2 234

Se você deseja imprimir contagens para todas as linhas, incluindo aquelas que aparecem apenas uma vez:

sort FILE | uniq -c

ou, com as opções longas do GNU (no Linux):

sort FILE | uniq --count

Para a entrada fornecida, a saída é:

  3 123
  2 234
  1 345

Para classificar a saída com as linhas mais frequentes no topo, você pode fazer o seguinte (para obter todos os resultados):

sort FILE | uniq -c | sort -nr

ou, para obter apenas linhas duplicadas, as mais frequentes primeiro:

sort FILE | uniq -cd | sort -nr

no OSX e no BSD, o final se torna:

sort FILE | uniq -c | grep -v '^ *1 ' | sort -nr

1
Bom argumento com a opção --repeated ou -d. Muito mais preciso do que usar "| grep 2" ou similar!
22713 Lauri

Como posso modificar este comando para recuperar todas as linhas cuja contagem de repetições é superior a 100?
Black_Rider

@Black_Rider Adicionar | sort -nou | sort -nrao pipe classificará a saída pela contagem de repetições (ascendente ou descendente, respectivamente). Não é isso que você está perguntando, mas achei que poderia ajudar.
Andrea

1
@Black_Rider awk parece capaz de fazer todos os tipos de cálculos: em seu caso, você poderia fazer| awk '$1>100'
Andrea

4
@fionbio Parece que você não pode usar -c e -d juntos no OSX uniq . Obrigado por apontar. Você pode usar o grep para filtrar linhas exclusivas :sort FILE | uniq -c | grep -v '^ *1 '
Andrea

72

Para localizar e contar linhas duplicadas em vários arquivos, você pode tentar o seguinte comando:

sort <files> | uniq -c | sort -nr

ou:

cat <files> | sort | uniq -c | sort -nr

30

Através da :

awk '{dups[$1]++} END{for (num in dups) {print num,dups[num]}}' data

No awk 'dups[$1]++'comando, a variável $1contém todo o conteúdo da coluna1 e colchetes são acesso à matriz. Portanto, para cada primeira coluna da linha no dataarquivo, o nó da matriz nomeada dupsé incrementado.

E, no final, estamos repetindo o dupsarray com a numvariável e imprimimos os números salvos primeiro e depois o número de valores duplicados dups[num].

Observe que seu arquivo de entrada possui espaços no final de algumas linhas; se você os esclarecer, poderá usar $0no lugar do $1comando acima :)


1
Não é um exagero, considerando o que temos uniq?
Nathan Fellman

9
sort | uniqe a solução awk possui vantagens e desvantagens em termos de desempenho e recursos: se os arquivos são grandes e o número de linhas diferentes é pequeno, a solução awk é muito mais eficiente. É linear no número de linhas e o uso do espaço é linear no número de linhas diferentes. OTOH, a solução awk precisa manter todas as diferentes linhas na memória, enquanto a classificação (GNU) pode recorrer a arquivos temporários.
Lars Noschinski

14

Nas janelas usando o "Windows PowerShell" , usei o comando mencionado abaixo para conseguir isso

Get-Content .\file.txt | Group-Object | Select Name, Count

Também podemos usar o Cmdlet where-object para filtrar o resultado

Get-Content .\file.txt | Group-Object | Where-Object { $_.Count -gt 1 } | Select Name, Count

você pode excluir todas as ocorrências das duplicatas, exceto a última ... sem alterar a ordem de classificação do arquivo?
Jparram

6

Supondo que você tenha acesso a um ambiente padrão do shell Unix e / ou cygwin:

tr -s ' ' '\n' < yourfile | sort | uniq -d -c
       ^--space char

Basicamente: converta todos os caracteres de espaço em quebras de linha, classifique a saída traduzida e alimente-a para uniq e conte linhas duplicadas.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.