Rimuovere le linee duplicate adiacenti mantenendo l'ordine


11

Ho un file con una colonna con nomi che si ripetono più volte ciascuno. Voglio condensare ogni ripetizione in una, mantenendo tutte le altre ripetizioni con lo stesso nome che non sono adiacenti ad altre ripetizioni con lo stesso nome.

Ad esempio, voglio girare il lato sinistro sul lato destro:

Golgb1    Golgb1    
Golgb1    Akna
Golgb1    Spata20
Golgb1    Golgb1
Golgb1    Akna
Akna
Akna
Akna
Spata20
Spata20
Spata20
Golgb1
Golgb1
Golgb1
Akna
Akna
Akna

Questo è quello che ho usato: perl -ne 'print if ++$k{$_}==1' file.txt > file2.txt tuttavia, questo metodo mantiene solo un rappresentante dalla sinistra (cioè Golb1 e Akna non si ripetono).

Esiste un modo per mantenere nomi univoci per ciascun blocco, mantenendo i nomi che si ripetono in più blocchi non adiacenti?

Risposte:


23

uniq farà questo per te:

$ uniq inputfile
Golgb1
Akna
Spata20
Golgb1
Akna

2
caspita è stato imbarazzantemente facile! Grazie!
Età

@ Age87 Unix è fantastico! Funziona solo perché ti aspetti che i duplicati siano già adiacenti (o, non desideri rimuovere quelli non adiacenti). Normalmente, la raccomandazione è di usaresort | uniq
jpaugh

1
O più succintamente, sort -u(:
DopeGhoti il

9

Awk soluzione:

awk '$1 != name{ print }{ name = $1 }' file.txt

L'output:

Golgb1
Akna
Spata20
Golgb1
Akna

6

Prova questo: salva la riga precedente e confronta con la riga corrente

$ perl -ne 'print if $p ne $_; $p=$_' ip.txt
Golgb1
Akna
Spata20
Golgb1
Akna

Anche tu hai taggato uniq- l'hai provato?

$ uniq ip.txt
Golgb1
Akna
Spata20
Golgb1
Akna

1

Con sed si può fare come segue:

sed -e '$!N;/^\(.*\)\n\1$/!P;D' input_file

Qui abbiamo nello spazio del pattern in qualsiasi momento 2 righe. Quando il confronto tra loro fallisce, stampiamo il primo e lo tagliamo dalla parte anteriore e torniamo indietro e aggiungiamo la riga successiva nello spazio del motivo. Sciacquare ... repeat

Utilizzando Perl in modalità slurp trattiamo l'intero file come una lunga stringa su cui viene applicato il regex che fa il confronto per te.

perl -0777pe 's//$1/ while /^(.*\n)\1+/gm' input_file

0

Domanda sulla soluzione sed di Rakesh Sharma.

Cosa succede se si dispone di un file di input come:

-126.1 48.206
-126.106 48.21
-126.11 48.212
-126.114 48.214
-126.116 48.216
-126.118 48.216
-126.128 48.222
-126.136 48.226

E vuoi che un file di output sia:

-126.1 48.206
-126.106 48.21
-126.11 48.212
-126.114 48.214
-126.116 48.216
-126.128 48.222
-126.136 48.226

Nota ciò che manca:

-126.118 48.216

So che il comando che voglio è simile alla tua soluzione:

sed -e '$!N;/^\(.*\)\n\1$/!P;D' input_file

Non puoi modificarlo nel modo giusto per stampare entrambe le colonne ed essere ordinato in questo modo speciale solo con i valori della colonna 2. Qualche consiglio?


sed -e '$!N' -e '/.*\.\([0-9]*\)\n.*\.\1$/!{P;D;}' -e 's/\n.*//;s/^/\n/;D' cancellerà i successivi elementi ripetitivi. Nota: questo richiede GNU sed. Per il POSIXcomportamento, ha bisogno di lievi modifiche.
Rakesh Sharma,
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.