GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Doppelte Felder in einer bestimmten Spalte entfernen?

Ich möchte aus einer bestimmten Spalte ($2 im Beispiel) die doppelten Felder (kommagetrennt) entfernen.

Eingabedatei:

A    1,2,3,4   
B    4,5,6,3
C    2,15

Erwartete Ausgabe:

A    1,2,3,4
B    5,6
C    15

Akzeptierte Antwort:

perl -lpe 's/sKS+/join ",", grep {!$seen{$_}++} split ",", $&/e'

Sie können das obige wie folgt ausführen:

$ perl -lpe 's/sKS+/join ",", grep {!$seen{$_}++} split ",", $&/e' afile 
A    1,2,3,4
B    5,6
C    15

Wie es funktioniert

Erster Aufruf von perl mit -lpe macht die folgenden 3 Dinge.

  • -l[octal] Zeilenende-Verarbeitung aktivieren, gibt Zeilenabschlusszeichen an
  • -p Schleife wie -n annehmen, aber auch Zeile drucken, wie sed
  • -e program eine Programmzeile (mehrere -e erlaubt, Programmdatei weglassen)

Dies nimmt im Wesentlichen die Datei auf, entfernt die Zeilenumbrüche, bearbeitet eine Zeile und fügt dann ein Zeilenumbruchzeichen wieder daran an, wenn es fertig ist. Es geht also nur durch die Datei und führt unseren Perl-Code nacheinander gegeneinander aus.

Was den eigentlichen Perl-Code betrifft:

  • s bedeutet ein Leerzeichen (die fünf Zeichen [ fnrt] und v in neueren Versionen von perl , wie [[:space:]] ).
  • K Behalte das Zeug links vom K, füge es nicht in $&
  • ein
  • S+ ein oder mehrere Zeichen nicht im Satz [ fnrtv]

Der join ",", nimmt die Ergebnisse und fügt jedes Feld wieder zusammen, sodass es durch ein Komma getrennt ist.

Der split ",", $& nimmt die Übereinstimmungen, die von S+ gefunden wurden und teilen Sie sie nur in die Felder auf, ohne das Komma.

Der grep {!$seen{$_}++} nimmt die Nummer jedes Felds und fügt sie dem Hash hinzu, $seen{} wobei die Nummer jedes Felds $_ ist während wir durch jeden von ihnen gehen. Jedes Mal, wenn eine Feldnummer „gesehen“ wird, wird sie über den ++ gezählt Operator, $seen{$_}++ .

Der grep{!$seen{$_}++} gibt einen Feldwert zurück, wenn er nur einmal gesehen wurde.

Geändert, um zu sehen, was passiert

Wenn Sie diese modifizierte Abscheulichkeit verwenden, können Sie sehen, was los ist, wenn dieser Perl-Einzeiler sich über die Zeilen der Datei bewegt.

$ perl -lpe 's/sKS+/join ",", grep {!$seen{$_}++} split ",", $&/e; @a=keys %seen; @b=values %seen; print "keys: @a | vals: @b"' afile 
keys: 4 1 3 2 | vals: 1 1 1 1
A    1,2,3,4
keys: 6 4 1 3 2 5 | vals: 1 2 1 2 1 1
B    5,6
keys: 6 4 1 3 2 15 5 | vals: 1 2 1 2 2 1 1
C    15

Dies zeigt Ihnen den Inhalt von $seen{} am Ende der Verarbeitung einer Zeile aus der Datei. Nehmen wir die zweite Zeile der Datei.

B    4,5,6,3

Und hier ist, was meine modifizierte Version diese Zeile als zeigt:

keys: 6 4 1 3 2 15 5 | vals: 1 2 1 2 2 1 1

Das bedeutet also, dass wir Feld Nr. 6 (1 Mal), Feld Nr. 4 (2 Mal) usw. und Feld Nr. 5 (1 Mal) gesehen haben. Wenn also grep{...} gibt die Ergebnisse zurück, es werden nur Ergebnisse aus diesem Array zurückgegeben, wenn es in dieser Zeile vorhanden war (4,5,6,3) und wenn wir es nur einmal gesehen haben (6,1,15,5). Die Schnittmenge dieser 2 Listen ist (5,6) und das wird von grep zurückgegeben .

Referenzen

  • perlre – perldoc.perl.org
Verwandte:Möglichkeit, eine Datei direkt zu ändern?
Linux
  1. So finden und entfernen Sie doppelte Fotos in Linux

  2. Entfernen Sie einen abgelaufenen Schlüssel in APT

  3. Wie entferne ich doppelte Zeilen in einer Textdatei?

  4. Zeilen basierend auf Duplikaten innerhalb einer Spalte ohne Sortierung entfernen?

  5. Zeilen drucken, wenn angegebene Spalte mit einem Großbuchstaben beginnt?

So entfernen Sie doppelte Zeilen in MySQL

So finden und entfernen Sie doppelte/unerwünschte Dateien in Linux mit dem Tool „FSlint“.

Befehl zum Aufheben der Verknüpfung in Linux (Datei entfernen)

So finden Sie doppelte Dateien in Linux und entfernen sie

Wie entferne ich doppelte Einträge im „Öffnen mit“-Nautilus-Dialog?

Wie kann ich doppelte Dateien in separaten Verzeichnisbäumen entfernen?