Stampa di linee uniche


15

Esiste una soluzione migliore per la stampa di linee uniche diverse da una combinazione di sorte uniq?


1
Cosa intendi con "migliore"?
gabe.

@gabe Ad esempio, non è necessario archiviare l'intero file in memoria.
Let_Me_Be

Alcune versioni di sort(ad es. GNU coreutils) usano file temporanei e mergesort esterni se l'input è troppo grande per adattarsi alla RAM. E la maggior parte delle altre versioni ha -mun'opzione in modo da poterlo fare esplicitamente tagliando l'input (ad es. Con split), ordinando ogni blocco e quindi unendo i blocchi
jhnc

Risposte:


25

Per stampare ogni riga identica solo una, in qualsiasi ordine:

sort -u

Per stampare solo le linee uniche, in qualsiasi ordine:

sort | uniq -u

Per stampare ogni riga identica una sola volta, nell'ordine della prima occorrenza: (per ogni riga, stampa la riga se non è stata ancora vista, quindi incrementa il contatore visualizzato)

awk '!seen[$0] {print}
     {++seen[$0]}'

Per stampare solo le righe univoche, nell'ordine della loro prima occorrenza: (registra ciascuna riga seene anche linesse è la prima occorrenza; alla fine dell'input, stampa le righe in ordine di occorrenza ma solo quelle visualizzate solo una volta)

awk '!seen[$0]++ {lines[i++]=$0}
     END {for (i in lines) if (seen[lines[i]]==1) print lines[i]}'

8
che ne dici awk '!seen[$0]++ {print}'?
asoundmove,

10
O ancora più breve awk '!seen[$0]++', dal momento che {print}è implicito da un comando vuoto.
Quazgar,

3

Alcune (la maggior parte?) Versioni di sorthanno un -uflag che fa uniqdirettamente la parte. Tuttavia, potrebbero esserci delle restrizioni sulla lunghezza della linea, a seconda dell'implementazione, ma ne avevi già di semplici sort|uniq.


1
Er? sort -uritorna almeno a V7.
geekosaur,

Hum ... Pensavo di essermi ricordato che Solaris o AIX non lo avevano. Mi sbaglio però, lo hanno entrambi.
Mat

Solaris e AIX hanno -uanche una limitazione della lunghezza della linea di 512 caratteri. (In realtà, penso che da qualche parte intorno a Solaris 9 Sun sia aumentato a 5120. Tuttavia GNU vince ancora.)
Geekosaur,

@geekosaur: sei sicuro? Il lavoro svolto per rimuovere il limite di 512 byte sulla lunghezza della linea in ordine è stato documentato in "Teoria e pratica nella costruzione di una routine di ordinamento funzionante" di JP Linderman, tecnico del sistema Bell. Journal, 63, 1827-1843 (1984).
Jonathan Leffler,

0

Perl funziona per te? Può mantenere le linee nell'ordine originale, anche se i duplicati non sono adiacenti. Puoi anche codificarlo in Python o awk.

while (<>) {
    print if $lines{$_}++ == 0;
}

Che può essere ridotto a solo

perl -ne 'print unless $lines{$_}++;'

Dato file di input:

abc
def
abc
ghi
abc
def
abc
ghi
jkl

Produce l'output:

abc
def
ghi
jkl

Dove vengono definite le $ $?
Gregg Leventhal,

Non lo è. Dal momento che non esiste un use strict;o use warnings;(in realtà, è strictquello più rilevante qui), non vi è alcun reclamo sull'uso %linesprima che sia definito. Se eseguito con le restrizioni, dovrebbe esserci una linea my %lines;prima del ciclo. Nota anche che l'hash è %lines; a un elemento dell'hash viene fatto riferimento usando la $lines{$_}notazione.
Jonathan Leffler,

Penso che le sortsoluzioni possano essere migliori per grandi quantità di dati (l'OP era preoccupato di "memorizzare l'intero file in memoria"). sorteseguirà un ordinamento out-of-core se i dati sono più grandi della memoria disponibile.
Kusalananda

0

Nell'ultima parte della risposta menzionata in: Stampa di linee uniche di @Gilles come risposta a questa domanda, ho cercato di eliminare la necessità di utilizzare due hash.

Questa soluzione è per: Per stampare solo le linee uniche, nell'ordine della loro prima occorrenza:

awk '{counter[$0]++} END {for (line in counter) if (counter[line]==1) print line}'

Qui, "counter" memorizza un conteggio di ogni riga simile a quello elaborato in precedenza.
Alla fine, stampiamo solo quelle righe che hanno un valore del contatore pari a 1.

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.