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?

È stato utile?

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top