Ich habe eine Datei, die wie dieses Spielzeugbeispiel aussieht. Meine eigentliche Datei enthält 4 Millionen Zeilen, von denen etwa 10 gelöscht werden müssen.
ID Data1 Data2
1 100 100
2 100 200
3 200 100
ID Data1 Data2
4 100 100
ID Data1 Data2
5 200 200
Ich möchte die Zeilen löschen, die wie die Überschrift aussehen, mit Ausnahme der ersten Zeile.
Endgültige Datei:
ID Data1 Data2
1 100 100
2 100 200
3 200 100
4 100 100
5 200 200
Wie kann ich das machen?
text-processing
Gaius Augustus
quelle
quelle
{ IFS= read -r head; printf '%s\n' "$head"; grep -vF "$head" ; } <file
head -1
wurde vor Jahrzehnten überholt.Sie können verwenden
Dadurch werden Zeilen mit der ID ab Zeile 2 gelöscht.
quelle
sed '2,${/^ID Data1 Data2$/d;}' file
(natürlich mit der richtigen Anzahl von Leerzeichen zwischen den Spalten)sed
s, nein.sed '1!{/ID/d;}'
Für diejenigen, die keine geschweiften Klammern mögen
n
bedeutetpass
Zeile Nr.1
d
Löschen Sie alle übereinstimmenden Zeilen, die mit "" beginnen^ID
quelle
sed '1n;/^ID/d'
Dateiname abgekürzt werden. Nur ein VorschlagIDfoo
die nicht mit der Kopfzeile identisch sind (in diesem Fall ist es unwahrscheinlich, dass dies einen Unterschied macht, aber Sie wissen es nie).Hier ist eine lustige. Sie können
sed
direkt verwenden, um alle Kopien der ersten Zeile zu entfernen und alles andere (einschließlich der ersten Zeile selbst) an Ort und Stelle zu lassen.1{h;n;}
Setzt die erste Zeile in den Haltebereich, druckt sie aus und liest die nächste Zeile ein. Der Rest dersed
Befehle für die erste Zeile wird übersprungen . (Es überspringt auch diesen ersten1
Test für die zweite Zeile , aber das spielt keine Rolle, da dieser Test nicht auf die zweite Zeile angewendet worden wäre.)G
Fügt eine neue Zeile, gefolgt vom Inhalt des Haltebereichs, an den Musterbereich an./^\(.*\)\n\1$/d
löscht den Inhalt des Musterbereichs (springt also zur nächsten Zeile), wenn der Teil nach der neuen Zeile (dh was aus dem Haltebereich angehängt wurde) genau mit dem Teil vor der neuen Zeile übereinstimmt. Hier werden Zeilen gelöscht, die den Header duplizieren.s/\n.*$//
Löscht den vomG
Befehl hinzugefügten Textabschnitt , sodass nur die Textzeile aus der Datei gedruckt wird.Da
P
reguläre Ausdrücke jedoch teuer sind, wäre ein etwas schnellerer Ansatz, dieselbe Bedingung (negiert) zu verwenden und bis zum Zeilenumbruch zu drucken, wenn der Teil nach dem Zeilenumbruch (dh was aus dem Laderaum angehängt wurde) nicht genau mit dem Teil übereinstimmt vor dem Zeilenumbruch und dann unbedingt den Musterraum löschen:Ausgabe, wenn Ihre Eingabe gegeben ist:
quelle
sed '1{h;n;};G;/^\(.*\)\n\1$/d;P;d' input
; irgendwie fällt mir das lesen leichter. :)Hier sind einige weitere Optionen, bei denen Sie die erste Zeile nicht im Voraus kennen müssen:
Das
-n
Flag weist Perl an, die Eingabedatei zu durchlaufen und jede Zeile als zu speichern$_
. Der$k=$_ if $.==1;
speichert die erste Zeile ($.
ist die Zeilennummer, gilt also$.==1
nur für die 1. Zeile) als$k
. Dasprint unless $k eq $_
druckt die aktuelle Zeile aus, wenn sie nicht mit der gespeicherten übereinstimmt$k
.Alternativ dazu dasselbe in
awk
:Hier testen wir, ob die aktuelle Zeile mit der in der Variablen gespeicherten übereinstimmt
x
. Wenn der Test$0!=x
mit true bewertet wird (wenn die aktuelle Zeile$0
nicht mit true übereinstimmtx
), wird die Zeile gedruckt, da die Standardaktion für awk für true-Ausdrücke das Drucken ist. Die erste Zeile (NR==1
) wird gespeichert alsx
. Da dies erfolgt, nachdem geprüft wurde, ob die aktuelle Zeile übereinstimmtx
, wird auch die erste Zeile gedruckt.quelle
!($0 in a)
testet ohne zu erstellen und vermeidet dies, oder awk kann die gleiche Logik wie für perl'$0!=x; NR==1{x=$0}'
'NR==1{x=$0;print} $0!=x'
!a[$0]
? Warum würde das einen Eintrag in erstellena
?AWK ist auch für diesen Zweck ein recht anständiges Werkzeug. Hier ist ein Codebeispiel:
Brechen :
NR == 1 {print}
sagt uns, dass wir die erste Zeile der Textdatei drucken sollenNR != 1 && $0!~/ID Data1 Data2/
Der logische Operator&&
weist AWK an, eine Zeile zu drucken, die ungleich 1 ist und keine enthältID Data1 Data2
. Beachten Sie das Fehlen eines{print}
Teils; Wenn in awk eine Testbedingung als wahr bewertet wird, wird angenommen, dass die Zeile gedruckt wird.| head -n 10
ist nur eine winzige Erweiterung, um die Ausgabe auf die ersten 10 Zeilen zu beschränken. Für dasAWK
Teil selbst nicht relevant , wird nur zu Demonstrationszwecken verwendet.Wenn Sie dies in einer Datei wünschen, leiten Sie die Ausgabe des Befehls um, indem Sie
> newFile.txt
am Ende des Befehls Folgendes anfügen:Wie hält es aus? Ziemlich gut eigentlich:
Randnotiz
Die generierte Beispieldatei wurde erstellt, um eine Schleife zwischen 1 und 1 Million zu erstellen und die ersten vier Zeilen Ihrer Datei zu drucken (also 4 Zeilen mal 1 Million entspricht 4 Millionen Zeilen). Dies dauerte übrigens 0,09 Sekunden.
quelle
ID Data1 Data2 foo
die nicht mit der Kopfzeile identisch sind (in diesem Fall ist es unwahrscheinlich, dass dies einen Unterschied macht, aber Sie wissen es nie).Awk, passt sich automatisch an jede Überschrift an:
dh in der ersten Zeile wird der Header abgerufen und gedruckt, und die nachfolgende Zeile DIFFERENT aus diesem Header wird gedruckt.
FNR = Anzahl der Datensätze in der aktuellen Datei, so dass Sie mehrere Dateien haben können, und es wird in jeder von ihnen dasselbe tun.
quelle
Der Vollständigkeit halber gab Perl-Lösung IMO etwas eleganter als @terdon:
quelle
ID
. Sie können nicht garantieren, dass dadurch nicht die Zeilen gelöscht werden, die beibehalten werden sollen. Da Sie Eleganz erzogen haben,g
ist es sinnlos, wenn Sie verwenden^
und verwendest$
. In der Tat sind alle Ihre Optionenm///
hier außer nutzloss
; Sie aktivieren Funktionen, die Sie nicht verwenden. So ist das$
,s/^ID.*//s
würde das gleiche tun.Nur um die Frage ein wenig zurückzudrängen ... es sieht so aus, als ob Ihre Eingabe selbst das Ergebnis des Zusammenpassens mehrerer TSV-Dateien ist. Wenn Sie einen Schritt in Ihrer Verarbeitungspipeline sichern können (wenn Sie das besitzen oder mit den Verantwortlichen sprechen können), können Sie die Daten zunächst mit einem Tool verketten, das den Header berücksichtigt, und so das Problem der Notwendigkeit beseitigen Entfernen Sie zusätzliche Kopfzeilen.
Zum Beispiel mit Miller :
quelle