Verifica che tutte le righe di un file siano univoche


11

Ho un file di testo contenente righe come questa:

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

Come posso essere sicuro dell'unicità di ogni linea?

NOTA: l'obiettivo è testare il file, non modificarlo se sono presenti righe duplicate.



1
Vuoi verificare se tutte le righe sono univoche o vuoi rimuovere eventuali duplicati?
8bittree,

1
@ 8bittree - desidero solo essere sicuro di unicità
snr

Risposte:


24
[ "$(wc -l < input)" -eq "$(sort -u input | wc -l)" ] && echo all unique

Esattamente quello che avrei detto, se non con uniqinvece disort -u
Nonny Moose l'

1
Se l'input non è già ordinato, uniqsarebbe un grosso errore; deduplica solo le linee adiacenti!
alexis,

1
Se uno è interessato ai colpevoli, a sort <file> | uniq -dstampa i duplicati.
Rolf,

25

Soluzione Awk:

awk 'a[$0]++{print "dupes"; exit(1)}' file && echo "no dupes"

4
+1 La risposta accettata legge l'intero file due volte, mentre questa si interrompe non appena incontra una riga duplicata in una lettura. Questo funzionerà anche con l'input di piping, mentre l'altro ha bisogno di file che può rileggere.
JoL

Non potresti spingerlo echodentro END?
Ignacio Vazquez-Abrams,

2
@ IgnacioVazquez-Abrams Non ha davvero senso l'eco. Fare && echoo || echoè una convenzione nelle risposte per indicare che un comando fa la cosa giusta con il codice dello stato di uscita. L'importante è il exit(1). Idealmente, lo useresti come if has_only_unique_lines file; then ..., no if [[ $(has_only_unique_lines file) = "no dupes" ]]; then ..., sarebbe sciocco.
JoL

2
Laddove altre risposte leggono il file due volte per risparmiare memoria, questo leggerà l'intero file in memoria, se non ci sono duplicati.
Kusalananda

1
@Kusalananda Mentre questo leggerà l'intero file in memoria quando non ci sono duplicati, usando sortanche la volontà, indipendentemente dal fatto che ci siano duplicati o no, giusto? Come sta risparmiando memoria?
JoL

21

Utilizzando sort/ uniq:

sort input.txt | uniq

Per verificare solo la presenza di righe duplicate, utilizzare l' -dopzione per uniq. Questo mostrerà solo le linee duplicate, se nessuna mostrerà nulla:

sort input.txt | uniq -d

Questo è il mio passaggio. Non sono sicuro di ciò che le altre risposte più votate offrono che questo non lo fa.
user1717828

1
È una buona alternativa per rimuovere i duplicati.
Snr

1
Questo non fa quello che vuole. Vuole sapere se ci sono duplicati, non rimuoverli.
Barmar,

@Barmar: Anche se sembra che la domanda non sia ancora chiara. Oltre ai commenti dei PO che tentano di chiarirlo.
jesse_b,

C'è una modifica in sospeso che aggiunge ulteriori chiarimenti.
Barmar,

5

TLDR

La domanda originale non era chiara e leggeva che l'OP voleva semplicemente una versione unica del contenuto di un file. Questo è mostrato di seguito. Nella forma aggiornata della domanda, l'OP ora sta dichiarando che vuole semplicemente sapere se il contenuto del file è unico o no.


Verifica se il contenuto del file è univoco o meno

Puoi semplicemente utilizzare sortper verificare se un file è univoco o contiene duplicati in questo modo:

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

Esempio

Di 'che ho questi due file:

file di esempio duplicato
$ 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
file di esempio univoco
$  cat uniq_input.txt
A
B
C
D

Ora quando analizziamo questi file possiamo dire se sono unici o contengono duplicati:

prova file duplicati
$ sort -uC dup_input.txt && echo "unique" || echo "duplicates"
duplicates
prova file univoco
$ sort -uC uniq_input.txt && echo "unique" || echo "duplicates"
unique

Domanda originale (contenuto univoco del file)

Può essere fatto solo con 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

Di solito sortil file, quindi uso uniqper contare il numero di duplicati, quindi sortancora una volta vedo i duplicati in fondo all'elenco.

Ho aggiunto un duplicato agli esempi forniti:

$ 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

Dato che non leggo la pagina man da uniqun po 'di tempo, ho dato una rapida occhiata a qualsiasi alternativa. Quanto segue elimina la necessità del secondo ordinamento, se vuoi solo vedere i duplicati:

$ sort thread.file | uniq -d
This is a thread  139737505302272

È davvero una buona alternativa. #rez
snr

2

Se non ci sono duplicati, tutte le righe sono uniche:

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

Descrizione: ordina le righe del file per rendere consecutive le righe ripetute (ordina)
Estrai tutte le righe consecutive uguali (uniq -d).
Se esiste un output del comando sopra ( [...]), quindi ( &&) stampa un messaggio.


2

Questo non sarebbe completo senza una risposta Perl!

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

Questo stamperà ogni riga non unica una volta: quindi se non stampa nulla, il file ha tutte le linee uniche.


1

Utilizzando cmpe sortin bash:

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

o

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

Questo però ordinerebbe il file due volte, proprio come la risposta accettata.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.