Entfernen von Zeilen mit nicht mehr oder weniger als 'N' Feldern?

9

Ich arbeite auf einem Mac mit sed, perl, awk, bash ..

Ich habe eine große Textdatei (10 GB) mit 13 Feldern (Spalten) mit TABbegrenzten Daten. Leider sind einige dieser Zeilen irrelevant TABs, daher möchte ich die gesamte Zeile löschen, in der wir zusätzliche TABs und damit ungleiche Felder haben. (Es macht mir nichts aus, die Zeilen in ihrer Gesamtheit zu verwerfen)

Was ich derzeit habe, schreibt die Anzahl der Felder in eine andere Datei.

awk -F'\t' '{print NF}' infile  > fieldCount

head fieldCount
13
13
10
13
13
13
14
13
13
13

Ich möchte ein kurzes Skript erstellen, das jede Zeile mit mehr (oder weniger) als 13 richtigen Feldern (aus der Originaldatei) entfernt.

  1. Geschwindigkeit ist hilfreich, da ich dies für mehrere Dateien tun muss
  2. es auf einmal zu machen wäre cool
  3. Ich portiere derzeit die fieldCount-Datei in Python und versuche, sie zeilenweise zu laden.

BEARBEITEN:

vaild (13 Spalten)

a       b       c       d       e       f       g       h       i       j       k       l       m

ungültig (14 Spalten)

a       b       c       d       e       f       g       h       i       j       k       l       m       n
T. Scharf
quelle
Können Sie als Beispiel angeben, welche gültige und welche ungültige Zeile gültig ist?
Cuonglm

Antworten:

11

Sie haben es fast schon:

awk -F '\ t' 'NF == 13 {print}' infile   > newfile

Und wenn Sie sich auf einem dieser Systeme befinden, auf denen Sie per Tastendruck (:)) belastet werden, können Sie dies auf verkürzen

awk -F '\ t' 'NF == 13' infile   > newfile

Um mehrere Dateien in einem Durchlauf auszuführen und die Dateien tatsächlich zu ändern (und nicht nur neue Dateien zu erstellen), identifizieren Sie einen Dateinamen, der nicht verwendet wird (z. B. scharf), und führen Sie eine Schleife wie die folgende aus:

für f in  Liste
tun
    awk -F '\ t' 'NF == 13 {print}' "$ f"> scharf && mv -f - scharf "$ f"
erledigt

Dies listkönnen ein oder mehrere Dateinamen und / oder Platzhalter-Dateinamen-Erweiterungsmuster sein. zum Beispiel,

für f in blue.data green.data * .dat orange.data red.data /ultra/violet.dat

Der mvBefehl überschreibt die Eingabedatei (z. B. blue.data) mit der temporären scharfDatei (die nur die Zeilen aus der Eingabedatei mit 13 Feldern enthält). (Stellen Sie sicher, dass Sie dies tun möchten, und seien Sie vorsichtig. Um sicher zu gehen, sollten Sie Ihre Daten wahrscheinlich zuerst sichern.) Der -fBefehl mvzum Überschreiben der Eingabedatei, obwohl diese bereits vorhanden ist. Das --schützt Sie vor Verrücktheit, wenn eine Ihrer Dateien einen Namen hat, der mit beginnt -.

G-Man sagt "Reinstate Monica"
quelle
Nur ein kleiner Schubs war alles, was ich brauchte - danke Partner
T. Scharf
2

Da es sich um eine große Datei handelt, kann es sich lohnen, ein etwas komplexeres Tool zu verwenden, um die Leistung zu steigern. In der Regel sind Spezialwerkzeuge schneller als allgemeine Werkzeuge. Zum Beispiel ist das Lösen des gleichen Problems mit cuttendenziell schneller als das, grepwas tendenziell schneller ist als das, sedwas tendenziell schneller ist als awk(die Kehrseite ist, dass spätere Werkzeuge Dinge tun können, die frühere nicht können).

Sie möchten Zeilen mit 13 oder mehr Tabulatorzeichen entfernen, also:

LC_ALL=C grep -Ev '(␉.*){13}'

oder vielleicht (ich erwarte keinen messbaren Leistungsunterschied)

LC_ALL=C grep -Ev '(␉.*){12}␉'

Wo ist ein wörtliches Tabulatorzeichen? Das Festlegen des Gebietsschemas auf Cist nicht erforderlich, beschleunigt jedoch einige Versionen von GNU grep im Vergleich zu Multibyte-Gebietsschemas.

Gilles 'SO - hör auf böse zu sein'
quelle
1

Mit perl:

perl -F'\t' -anle 'print if @F == 13' file

Fügen Sie zum Bearbeiten an Ort und Stelle die -iOption hinzu:

perl -i.bak -F'\t' -anle 'print if @F == 13' file
cuonglm
quelle
danke Gnouc - Ich muss G-mans Antwort akzeptieren, dass er dich um ein paar Minuten geschlagen hat. Aber ich weiß es wirklich zu schätzen
T. Scharf
@ T.Scharf: Ich denke, meine ist besser, wenn Sie mit mehreren Dateien arbeiten möchten. Aber es macht Ihnen nichts aus, das Beste für Sie auszuwählen.
Cuonglm