2009-04-14 19 views
13

Ho uno strumento che genera test e predice l'output. L'idea è che se ho un fallimento posso confrontare la previsione con l'output effettivo e vedere dove si sono separati. Il problema è che l'output effettivo contiene alcune righe due volte, il che confonde lo diff. Voglio rimuovere i duplicati, in modo da poterli confrontare facilmente. Fondamentalmente, qualcosa come sort -u ma senza l'ordinamento.strumento unix per rimuovere le righe duplicate da un file

C'è qualche strumento di comando unix in grado di farlo?

+0

Eventuali duplicati di [Come posso eliminare linee duplicate in un file in Unix?] (Http://stackoverflow.com/questions/1444406/how-can-i-delete-duplicate-lines-in- a-file-in-unix) –

risposta

18

uniq(1)

RIEPILOGO

uniq [OPZIONE] ... [INPUT [OUTPUT]]

DESCRIZIONE

Elimina tutti tranne uno successive linee identiche da INPUT (o input standard), scrivendo su OUTPUT (o output standard).

Oppure, se si desidera rimuovere non adiacenti linee duplicate così, questo frammento di perl lo farà:

while(<>) { 
    print $_ if (!$seen{$_}); 
    $seen{$_}=1; 
} 
+0

La risposta Perl funziona solo se si desidera il primo elemento. L'ultima sarebbe una soluzione diversa. – Xetius

+1

E per chi non sa come usare Perl, questo è tutto ciò che è necessario digitare: perl -pe 'stampare a meno di $ visto {$ _} ++' [INPUT]> OUTPUT – reinierpost

+0

@Xetuis, loro ' re la stessa riga :) Se si desidera l'ultima riga, è sufficiente impostare la voce vista sul numero di riga, non stampare nel ciclo, quindi stamparli in ordine di numero di riga alla fine. Ma non penso che sia nesso in questo caso. –

1

Se siete interessati a rimuovere adiacenti linee duplicate, utilizzare uniq .

Se si desidera rimuovere tutte le righe duplicate, non solo quelle adiacenti, quindi è più difficile.

1

Ecco cosa mi è venuto in mente mentre stavo aspettando una risposta qui (anche se la prima risposta (e accettata) è arrivata in circa 2 minuti). Ho usato questa sostituzione in VIM:

%s/^\(.*\)\n\1$/\1/ 

Il che significa: cerca linee dove, dopo il ritorno a capo che abbiamo la stessa di prima, e sostituirli solo con quello che abbiamo catturato nella prima riga.

uniq è decisamente più semplice, però.

24

Complementare alle risposte uniq, che funzionano benissimo se non ti dispiace sort prima di tutto. Se è necessario rimuovere le linee non adiacenti (o se si desidera rimuovere i duplicati, senza riordinare il file), il seguente Perl one-liner dovrebbe farlo (rubato da here):

cat textfile | perl -ne '$H{$_}++ or print' 
+0

Penso che questa sia una risposta chiara. Sono stato programmatore in Perl per circa 6 anni e non avrei mai pensato a qualcosa di così conciso – Xetius

+1

La parte Perl è davvero elegante. Questo, tuttavia, si qualifica per il premio "Useless Use of cat" :-) (vedi http://partmaps.org/era/unix/award.html). Basta usare " sleske

+2

Non avevo mai sentito parlare di quel premio! Sì, a volte uso gatto piuttosto gratuitamente; Non ho idea del motivo per cui "cat x |" sembra meglio di " y "mi fa sanguinare gli occhi: P –

1

Ecco un'implementazione awk , nel caso in cui l'ambiente non abbia/permetta perl (non ne ho ancora visto uno)! PS: se ci sono più di una linea duplicata, allora stampa le copie duplicate.

awk '{ 

# Cut out the key on which duplicates are to be determined. 
key = substr($0,2,14) 

#If the key is not seen before, store in array,else print 
if (! s[key]) 
    s[key] = 1; 
else 
    print key; 
}' 
+4

Se stai guardando l'intera linea come chiave, questo è analogo alle soluzioni perl: 'awk '! C [$ 0] ++' file' –

Problemi correlati