Come mantenere il formato di un file se si utilizza il comando uniq (nella shell)?
-
22-07-2019 - |
Domanda
Per usare il comando uniq, devi prima ordinare il tuo file.
Ma nel file che ho, l'ordine delle informazioni è importante, quindi come posso mantenere il formato originale del file ma ancora liberarmi di contenuti duplicati?
Soluzione
Un'altra versione di awk:
awk '!_[<*>]++' infile
Altri suggerimenti
Questo awk
mantiene la prima occorrenza. Stesso algoritmo delle altre risposte utilizzate:
awk '!(sort file | uniq -d | awk '
FNR == NR { dups[<*>] }
FNR != NR && (!(<*> in dups) || !lines[<*>]++)
' - file
in lines) { print <*>; lines[<*>]; }'
Eccone uno che deve solo memorizzare righe duplicate (al contrario di tutte le righe) usando awk
:
C'è anche il numero di riga " doppio ordinamento " metodo.
nl -n ln | sort -u -k 2| sort -k 1n | cut -f 2-
Puoi eseguire uniq -d sulla versione ordinata del file per trovare le righe duplicate, quindi eseguire alcuni script che dicono:
if this_line is in duplicate_lines {
if not i_have_seen[this_line] {
output this_line
i_have_seen[this_line] = true
}
} else {
output this_line
}
Utilizzando solo uniq e grep:
Crea d.sh:
#!/bin/sh
sort $1 | uniq > $1_uniq
for line in $(cat $1); do
cat $1_uniq | grep -m1 $line >> $1_out
cat $1_uniq | grep -v $line > $1_uniq2
mv $1_uniq2 $1_uniq
done;
rm $1_uniq
Esempio:
./d.sh infile
Potresti usare qualcosa di orribile O (n ^ 2), come questo (pseudo-codice):
file2 = EMPTY_FILE
for each line in file1:
if not line in file2:
file2.append(line)
Questo è potenzialmente piuttosto lento, specialmente se implementato a livello di Bash. Ma se i tuoi file sono ragionevolmente brevi, probabilmente funzionerà bene, e sarebbe veloce da implementare ( non line in file2
è quindi solo grep -v
e così via ).
Altrimenti potresti ovviamente codificare un programma dedicato, usando una struttura di dati più avanzata in memoria per accelerarlo.
for line in $(sort file1 | uniq ); do
grep -n -m1 line file >>out
done;
sort -n out
prima fai l'ordinamento,
per ogni valore uniqe grep per la prima corrispondenza (-m1)
e conserva i numeri di riga
ordina numericamente l'output (-n) per numero di riga.
puoi quindi rimuovere la linea # con sed o awk