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.



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

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"

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

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

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

É 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.


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.


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.

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.