Verifique se todas as linhas de um arquivo são únicas

11

Eu tenho um arquivo de texto contendo linhas como esta:

This is a thread  139737522087680
This is a thread  139737513694976
This is a thread  139737505302272
This is a thread  139737312270080
.
.
.
This is a thread  139737203164928
This is a thread  139737194772224
This is a thread  139737186379520

Como posso ter certeza da singularidade de cada linha?

NOTA: O objetivo é testar o arquivo, não modificá-lo se houver linhas duplicadas.

snr
fonte
1
Linkando em: unix.stackexchange.com/q/76049/117549
Jeff Schaller
1
Deseja verificar se todas as linhas são exclusivas ou deseja remover duplicatas?
8bittree
1
@ 8bittree - desejo de apenas a certeza de singularidade
snr

Respostas:

24
[ "$(wc -l < input)" -eq "$(sort -u input | wc -l)" ] && echo all unique
Jeff Schaller
fonte
Exatamente o que eu teria dito, exceto com uniqem vez desort -u
Nonny Moose
1
Se a entrada ainda não estiver classificada, uniqseria um grande erro; apenas desduplica as linhas adjacentes!
Alexis
1
Se alguém estiver interessado nos culpados, a sort <file> | uniq -dimprimirá as duplicatas.
Rolf
25

Solução Awk:

awk 'a[$0]++{print "dupes"; exit(1)}' file && echo "no dupes"
iruvar
fonte
4
+1 A resposta aceita lê o arquivo inteiro duas vezes, enquanto isso para assim que encontra uma linha duplicada em uma leitura. Isso também funcionará com entrada canalizada, enquanto o outro precisa de arquivos que possam ser lidos novamente.
JOL
Você não poderia empurrar o echopara dentro END?
Ignacio Vazquez-Abrams
2
@ IgnacioVazquez-Abrams Não há realmente nenhum ponto no eco. Fazer && echoou || echoé uma convenção nas respostas para indicar que um comando faz a coisa certa com o código de status de saída. O importante é o exit(1). Idealmente, você usaria isso como if has_only_unique_lines file; then ..., não if [[ $(has_only_unique_lines file) = "no dupes" ]]; then ..., isso seria bobo.
7118 JoL
2
Onde outras respostas leem o arquivo duas vezes para economizar memória, isso lê o arquivo inteiro na memória, se não houver enganos.
Kusalananda
1
@Kusalananda Enquanto isso lê o arquivo inteiro na memória quando não há dupes, o uso de sortwill também, independentemente de haver dupes ou não, certo? Como isso está economizando memória?
JOL
21

Usando sort/ uniq:

sort input.txt | uniq

Para verificar apenas linhas duplicadas, use a -dopção uniq. Isso mostrará apenas as linhas duplicadas; caso contrário, não mostrará nada:

sort input.txt | uniq -d
jesse_b
fonte
Este é o meu caminho. Não tenho certeza do que as outras respostas com maior número de votos oferecem que essa não oferece.
User1717828
1
É uma boa alternativa para remover duplicatas.
snr
1
Isso não faz o que ele quer. Ele quer saber se há duplicatas, não removê-las.
Barmar 06/07/19
@ Barmar: Embora pareça assim, a questão ainda não está clara. Assim como os OPs comentam, tentando esclarecê-lo.
Jesson #
Há uma edição pendente que adiciona mais esclarecimentos.
226 Barmar
5

TLDR

A pergunta original não era clara e lia-se que o OP simplesmente desejava uma versão exclusiva do conteúdo de um arquivo. Isso é mostrado abaixo. Na forma atualizada da pergunta, o OP agora está declarando que ele / ela simplesmente deseja saber se o conteúdo do arquivo é único ou não.


Teste se o conteúdo do arquivo é único ou não

Você pode simplesmente usar sortpara verificar se um arquivo é exclusivo ou contém duplicatas como:

$ sort -uC input.txt && echo "unique" || echo "duplicates"

Exemplo

Digamos que eu tenho esses dois arquivos:

arquivo de amostra duplicado
$ cat dup_input.txt
This is a thread  139737522087680
This is a thread  139737513694976
This is a thread  139737505302272
This is a thread  139737312270080
This is a thread  139737203164928
This is a thread  139737194772224
This is a thread  139737186379520
arquivo de amostra exclusivo
$  cat uniq_input.txt
A
B
C
D

Agora, quando analisamos esses arquivos, podemos dizer se eles são únicos ou contêm duplicatas:

arquivo de duplicatas de teste
$ sort -uC dup_input.txt && echo "unique" || echo "duplicates"
duplicates
arquivo exclusivo de teste
$ sort -uC uniq_input.txt && echo "unique" || echo "duplicates"
unique

Pergunta original (conteúdo exclusivo do arquivo)

Pode ser feito com apenas sort:

$ sort -u input.txt
This is a thread  139737186379520
This is a thread  139737194772224
This is a thread  139737203164928
This is a thread  139737312270080
This is a thread  139737505302272
This is a thread  139737513694976
This is a thread  139737522087680
slm
fonte
3

Eu costumo sortusar o arquivo, depois uso uniqpara contar o número de duplicatas e, depois, sortvejo as duplicatas no final da lista.

Adicionei uma duplicata aos exemplos que você forneceu:

$ sort thread.file | uniq -c | sort
      1 This is a thread  139737186379520
      1 This is a thread  139737194772224
      1 This is a thread  139737203164928
      1 This is a thread  139737312270080
      1 This is a thread  139737513694976
      1 This is a thread  139737522087680
      2 This is a thread  139737505302272

Como não li a página do manual por uniqum tempo, dei uma olhada rápida em qualquer alternativa. O seguinte elimina a necessidade do segundo tipo, se você deseja apenas ver duplicados:

$ sort thread.file | uniq -d
This is a thread  139737505302272
Carlos Hanson
fonte
É uma boa alternativa mesmo. #rez
snr
2

Se não houver duplicatas, todas as linhas serão exclusivas:

[ "$(sort file | uniq -d)" ] && echo "some line(s) is(are) repeated"

Descrição: classifique as linhas do arquivo para tornar as linhas repetidas consecutivas (classificar)
Extraia todas as linhas consecutivas iguais (uniq -d).
Se houver alguma saída do comando acima ( [...]), ( &&) imprima uma mensagem.

NotAnUnixNazi
fonte
2

Isso não seria completo sem uma resposta Perl!

$ perl -ne 'print if ++$a{$_} == 2' yourfile

Isso imprimirá cada linha não exclusiva uma vez: portanto, se não imprimir nada, o arquivo terá todas as linhas exclusivas.

frapadingue
fonte
1

Usando cmpe sortem bash:

cmp -s <( sort file ) <( sort -u file ) && echo 'All lines are unique'

ou

if cmp -s <( sort file ) <( sort -u file )
then
    echo 'All lines are unique'
else
    echo 'At least one line is duplicated'
fi

Isso ordenaria o arquivo duas vezes, assim como a resposta aceita.

Kusalananda
fonte