Come ottenere solo risultati unici senza dover ordinare i dati?


40
$ cat data.txt 
aaaaaa
aaaaaa
cccccc
aaaaaa
aaaaaa
bbbbbb
$ cat data.txt | uniq
aaaaaa
cccccc
aaaaaa
bbbbbb
$ cat data.txt | sort | uniq
aaaaaa
bbbbbb
cccccc
$

Il risultato di cui ho bisogno è di visualizzare tutte le righe dal file originale rimuovendo tutti i duplicati (non solo quelli consecutivi), mantenendo l'ordine originale delle istruzioni nel file .

Qui, in questo esempio, il risultato che stavo effettivamente cercando era

aaaaaa
cccccc
bbbbbb

Come posso eseguire questa uniqoperazione generalizzata in generale?

Risposte:


54
perl -ne 'print unless $seen{$_}++' data.txt

Oppure, se devi avere un uso inutile dicat :

cat data.txt | perl -ne 'print unless $seen{$_}++'

Ecco una awktraduzione, per i sistemi che non hanno Perl:

awk '!seen[$0]++' data.txt
cat data.txt | awk '!seen[$0]++'

3
Uno script awk leggermente più breve è{ if (!seen[$0]++) print }
camh,

1
@fred, a meno che il tuo file non sia davvero enorme, entrambe le versioni impiegano più tempo a digitare di quante non lo siano per essere eseguite.
cjm

8
La versione awk può essere reso ancora più breve tralasciando il if, print, parentesi e bretelle:awk '!seen[$0]++'
Gordon Davisson

2
@Legate, è il nome di un array in cui stiamo registrando ogni riga che abbiamo visto. Potresti cambiarlo in '!LarryWall[$0]++'per tutte le preoccupazioni, ma "visto" aiuta le persone a capire meglio il programma.
cjm

1
@Sadi, che avrebbe dovuto essere posto come una domanda, non come un commento. Ma alcune delle righe in quel file finiscono in uno spazio, altre no. Questi comandi considerano significativa l'intera riga, incluso lo spazio bianco alla fine.
cjm

13

john ha uno strumento chiamato unique:

usr@srv % cat data.txt | unique out
usr@srv % cat out
aaaaaa
cccccc
bbbbbb

Ottenere lo stesso senza strumenti aggiuntivi in ​​una singola riga di comando è un po 'più complesso:

usr@srv % cat data.txt | nl | sort -k 2 | uniq -f 1 | sort -n | sed 's/\s*[0-9]\+\s\+//'
aaaaaa
cccccc
bbbbbb

nlstampa i numeri delle linee davanti alle linee, quindi se noi sort/ uniqdietro di loro, possiamo ripristinare l'ordine originale delle linee. sedelimina solo i numeri di riga in seguito;)


c'è qualche combinazione di comandi Linux comuni che potrebbero fare lo stesso?
Lazer,

7
Cosa ti sei perso in "senza dover ordinare i dati"?
Totor

@Totor - vedi la risposta di menkus a un commento simile. @binfalse - la tua seconda soluzione non funziona (forse funziona con questo banale esempio ma non funziona con alcuni input di vita reale). nl -ba -nrz data.txt | sort -k2 -u | sort | cut -f2
Risolvi

6

Preferisco usare questo:

cat -n data.txt | sort --key=2.1 -b -u | sort -n | cut -c8-

cat -n aggiunge numeri di riga,

sort --key=2.1 -b -u ordina sul secondo campo (dopo i numeri di riga aggiunti), ignorando gli spazi vuoti iniziali, mantenendo le linee uniche

sort -n ordina in stretto ordine numerico

cut -c8- mantenere tutti i caratteri dalla colonna 8 a EOL (ovvero omettere i numeri di riga inclusi)


5
> Come ottenere solo risultati unici senza dover ordinare i dati? > senza dover ordinare i dati
Jan Wikholm,

7
'senza dover ordinare i dati' appare solo nel titolo. L'esigenza effettiva è: "visualizzare tutte le righe dal file originale rimuovendo tutti i duplicati (non solo quelli consecutivi), mantenendo l'ordine originale delle istruzioni nel file".
menkus,

1
@menkus la chiave è "mantenendo l'ordine originale delle istruzioni nel file". Questa risposta non ci riesce.
Andrew Ferrier,

2

Perl ha un modulo che puoi usare che include una funzione chiamata uniq. Quindi, se hai caricato i tuoi dati in un array in Perl, devi semplicemente chiamare la funzione in questo modo per renderlo unico, mantenendo comunque l'ordine originale.

use List::MoreUtils qw(uniq)    
@output = uniq(@output);

Puoi leggere di più su questo modulo qui: Elenco :: MoreUtils


Questo può gestire file enormi, ad esempio 500 GB?
Ragazzo,
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.