Entfernen Sie benachbarte doppelte Zeilen, während Sie die Reihenfolge beibehalten


11

Ich habe eine Datei mit einer Spalte mit Namen, die sich jeweils mehrmals wiederholen. Ich möchte jede Wiederholung zu einer zusammenfassen, während alle anderen Wiederholungen mit demselben Namen beibehalten werden, die nicht an andere Wiederholungen mit demselben Namen angrenzen.

ZB möchte ich die linke Seite zur rechten Seite drehen:

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

Dies ist, was ich verwendet habe: perl -ne 'print if ++$k{$_}==1' file.txt > file2.txt Diese Methode hält jedoch nur einen Vertreter von links (dh Golb1 und Akna werden nicht wiederholt).

Gibt es eine Möglichkeit, eindeutige Namen für jeden Block beizubehalten, während Namen beibehalten werden, die sich in mehreren nicht benachbarten Blöcken wiederholen?

Antworten:


23

uniq wird dies für Sie tun:

$ uniq inputfile
Golgb1
Akna
Spata20
Golgb1
Akna

2
wow das war peinlich einfach! Vielen Dank!
Alter87

@ Age87 Unix ist großartig! Dies funktioniert nur, weil Sie erwarten, dass Duplikate bereits benachbart sind (oder nicht benachbarte Duplikate nicht entfernen möchten). Normalerweise ist die Empfehlung zu verwendensort | uniq
jpaugh

1
Oder prägnanter sort -u(:
DopeGhoti

9

Awk Lösung:

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

Die Ausgabe:

Golgb1
Akna
Spata20
Golgb1
Akna

6

Versuchen Sie dies - speichern Sie die vorherige Zeile und vergleichen Sie sie mit der aktuellen Zeile

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

Sie haben auch getaggt uniq- haben Sie es versucht?

$ uniq ip.txt
Golgb1
Akna
Spata20
Golgb1
Akna

1

Mit sed kann es wie folgt gemacht werden:

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

Hier haben wir im Musterraum jederzeit 2 Zeilen. Wenn der Vergleich zwischen ihnen fehlschlägt, drucken wir die erste und hacken sie von vorne und gehen zurück und fügen die nächste Zeile in den Musterbereich ein. Spülen ... wiederholen

Wenn Sie Perl im Slurp-Modus verwenden, behandeln wir die gesamte Datei als eine lange Zeichenfolge, auf die der reguläre Ausdruck angewendet wird, der den Vergleich für Sie durchführt.

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

0

Frage zu Rakesh Sharmas Sed-Lösung.

Was ist, wenn Sie eine Eingabedatei haben wie:

-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

Und Sie möchten, dass eine Ausgabedatei wie folgt lautet:

-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

Beachten Sie die fehlenden:

-126.118 48.216

Ich weiß, dass der gewünschte Befehl Ihrer Lösung ähnlich ist:

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

Kann nicht richtig geändert werden, um beide Spalten zu drucken, und kann nur auf diese spezielle Weise mit Werten für Spalte 2 sortiert werden. Irgendwelche Tipps?


sed -e '$!N' -e '/.*\.\([0-9]*\)\n.*\.\1$/!{P;D;}' -e 's/\n.*//;s/^/\n/;D' löscht die nachfolgenden sich wiederholenden Elemente. Hinweis: Dies erfordert GNU sed. Für das POSIXVerhalten muss es leicht geändert werden.
Rakesh Sharma
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.