Usuń sąsiadujące duplikaty linii, zachowując kolejność


11

Mam plik z jedną kolumną z nazwami, które powtarzają się kilka razy. Chcę zagęścić każde powtórzenie w jedno, zachowując wszystkie inne powtórzenia o tej samej nazwie, które nie sąsiadują z innymi powtórzeniami o tej samej nazwie.

Np. Chcę obrócić lewą stronę na prawą stronę:

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

Właśnie tego perl -ne 'print if ++$k{$_}==1' file.txt > file2.txt używałem : jednak ta metoda zachowuje tylko jednego przedstawiciela z lewej strony (tzn. Golb1 i Akna nie są powtarzane).

Czy istnieje sposób na zachowanie unikalnych nazw dla każdego bloku, przy jednoczesnym zachowaniu nazw powtarzających się w wielu, nie sąsiadujących blokach?

Odpowiedzi:


23

uniq zrobi to dla ciebie:

$ uniq inputfile
Golgb1
Akna
Spata20
Golgb1
Akna

2
wow, to było żenująco łatwe! dzięki!
Wiek87

@ Age87 Unix jest świetny! Działa to tylko dlatego, że spodziewasz się, że duplikaty już sąsiadują (lub nie chcesz usuwać niesąsiadujących). Zwykle zaleca się stosowaniesort | uniq
jpaugh

1
Lub bardziej zwięźle, sort -u(:
DopeGhoti

9

Awk rozwiązanie:

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

Wyjście:

Golgb1
Akna
Spata20
Golgb1
Akna

6

Spróbuj tego - zapisz poprzednią linię i porównaj z bieżącą linią

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

Ty też oznaczyłeś tagiem uniq- próbowałeś?

$ uniq ip.txt
Golgb1
Akna
Spata20
Golgb1
Akna

1

Z sed można to zrobić w następujący sposób:

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

Tutaj mamy w przestrzeni wzorów w dowolnym momencie 2 linie. Kiedy porównanie między nimi nie powiedzie się, drukujemy pierwszy, odcinamy go od przodu, cofamy i dołączamy następny wiersz do obszaru wzorów. Spłucz ... powtórz

Korzystając z Perla w trybie slurp, traktujemy cały plik jako jeden długi ciąg znaków, na którym zastosowano regex, który dokonuje porównania dla Ciebie.

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

0

Pytanie o sed rozwiązanie Rakesha Sharmy.

Co jeśli masz plik wejściowy, taki jak:

-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

I chcesz, aby plik wyjściowy był:

-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

Zwróć uwagę na brakujące:

-126.118 48.216

Wiem, że polecenie, które chcę, jest podobne do twojego rozwiązania:

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

Nie można go zmienić we właściwy sposób, aby wydrukować obie kolumny i można go sortować tylko w ten specjalny sposób z wartościami kolumny 2. Jakieś wskazówki?


sed -e '$!N' -e '/.*\.\([0-9]*\)\n.*\.\1$/!{P;D;}' -e 's/\n.*//;s/^/\n/;D' usunie kolejne powtarzające się elementy. Uwaga: Wymaga to GNU sed. Do POSIXzachowania wymaga drobnych zmian.
Rakesh Sharma
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.