2012-02-21 15 views
119

Voglio rimuovere voci duplicate da un file di testo, per esempio:Rimuovere le voci duplicate utilizzando uno script Bash

kavitha= Tue Feb 20 14:00 19 IST 2012 (duplicate entry) 
sree=Tue Jan 20 14:05 19 IST 2012 
divya = Tue Jan 20 14:20 19 IST 2012 
anusha=Tue Jan 20 14:45 19 IST 2012 
kavitha= Tue Feb 20 14:00 19 IST 2012 (duplicate entry) 

Esiste un modo possibile per rimuovere le voci duplicate utilizzando uno script Bash?

output desiderato

kavitha= Tue Feb 20 14:00 19 IST 2012 
sree=Tue Jan 20 14:05 19 IST 2012 
divya = Tue Jan 20 14:20 19 IST 2012 
anusha=Tue Jan 20 14:45 19 IST 2012 
+17

* Chiedere come rimuovere i duplicati. La domanda viene contrassegnata come duplicata. * – sysfiend

+0

* Questa è una domanda sulla rimozione di duplicati. È stato contrassegnato come duplicato. * –

risposta

264

Puoi sort quindi uniq:

$ sort -u input.txt 

Oppure utilizzare awk:

$ awk '!a[$0]++' input.txt 
+38

Test con un file di testo di 18.500 righe: 'sort ...' richiede circa 0.57s mentre 'awk ...' richiede circa 0.08s perché 'awk ...' rimuove semplicemente i duplicati senza ordinamento. – Hugo

+2

@Hugo Posso farlo. Provando contro 2.626.198 linee 'awk' batte' ordina'. I risultati mostrano 'awk' prendendo 5.675 e' sort' prendendo 5.675. È interessante notare che lo stesso set di record impiegava 15,1 secondi per eseguire una query DISTINCT su MySQL. –

+0

@TeganSnyder Hai scritto che entrambi i comandi richiedevano esattamente lo stesso tempo di esecuzione. Non è stato necessario "awk" per impiegare meno tempo? – jarno

7

Elimina duplicati, righe consecutive da un f ile (emula "uniq").
La prima riga di un insieme di righe duplicate viene mantenuta, il resto viene eliminato.

sed '$!N; /^\(.*\)\n\1$/!P; D' 
+0

per me, Un'altra aggiunta per altri usi, Se vuoi cambiare il file stesso qui è il comando 'sed -i '$! N; /^\(.*\)\n\1$/!P; D ' ' –

0

Questo potrebbe funzionare per voi:

cat -n file.txt | 
sort -u -k2,7 | 
sort -n | 
sed 's/.*\t/ /;s/\([0-9]\{4\}\).*/\1/' 

o questo:

awk '{line=substr($0,1,match($0,/[0-9][0-9][0-9][0-9]/)+3);sub(/^/," ",line);if(!dup[line]++)print line}' file.txt 
2

Perl one-liner simile alla soluzione awk @ Kev:

perl -ne 'print if ! $a{$_}++' input 

Questa variazione rimuove gli spazi bianchi finali prima di confrontare:

perl -lne 's/\s*$//; print if ! $a{$_}++' input 

Questa variazione modifica il file sul posto:

perl -i -ne 'print if ! $a{$_}++' input 

Questa variazione modifica il file sul posto, e fa un backup input.bak

perl -i.bak -ne 'print if ! $a{$_}++' input