awk Ausgabe in Datei basierend auf Filter

Oct 21 2020

Ich habe eine große CSVDatei, die ich basierend auf dem Wert in einer der Spalten in verschiedene Teile schneiden muss. Meine Eingabedatei sieht dataset.csvungefähr so ​​aus:

HINWEIS : Bearbeitet, um zu verdeutlichen, dass Daten ,data,keine Leerzeichen sind.

action,action_type, Result
up,1,stringA
down,1,strinB
left,2,stringC

Zum action_typeTeilen mache ich das einfach (ich brauche die gesamte übereinstimmende Zeile in der resultierenden Datei):

awk -F, '$2 ~ /^1$/ {print}' dataset.csv >> 1_dataset.csv
awk -F, '$2 ~ /^2$/ {print}' dataset.csv >> 2_dataset.csv

Dies funktioniert wie erwartet, aber ich durchlaufe meinen ursprünglichen Datensatz grundsätzlich zweimal. Mein ursprünglicher Datensatz ist ungefähr 5 GB groß und ich habe 30 action_typeKategorien. Ich muss das jeden Tag tun, also muss ich das Ding so schreiben, dass es effizient von alleine läuft.

Ich habe Folgendes versucht, aber es funktioniert nicht:

# This is a file called myFilter.awk

{
action_type=$2; if (action_type=="1") print $0 >> 1_dataset.csv;
else if (action_type=="2") print $0 >> 2_dataset.csv;
}

Dann führe ich es aus als:

awk -f myFilter.awk dataset.csv

Aber ich bekomme nichts. Im wahrsten Sinne des Wortes nichts, keine Fehler. Welche Art von sagen mir, dass mein Code einfach nicht mit irgendetwas übereinstimmt oder meine print / pipe-Anweisung falsch ist.

Antworten

4 anubhava Oct 21 2020 at 04:16

Sie können diese awk versuchen, um dies in einem einzigen Befehl zu tun:

awk -F, 'NR > 1{fn = $2 "_dataset.csv"; print >> fn; close(fn)}' file
3 EdMorton Oct 21 2020 at 05:12

Mit GNU awk können viele gleichzeitig geöffnete Dateien verarbeitet werden, ohne dass die Kopfzeile in jeder Ausgabedatei repliziert wird:

awk -F',' '{print > ($2 "_dataset.csv")}' dataset.csv

oder wenn Sie auch möchten, dass die Kopfzeile in jeder Ausgabedatei angezeigt wird, dann mit GNU awk:

awk -F',' '
    NR==1 { hdr = $0; next }
    !seen[$2]++ { print hdr > ($2 "_dataset.csv") }
    { print > ($2 "_dataset.csv") }
' dataset.csv

oder das gleiche mit jedem awk:

awk -F',' '
    NR==1 { hdr = $0; next }
    { out = $2 "_dataset.csv" } !seen[$2]++ { print hdr > out }
    { print >> out; close(out) }
' dataset.csv
1 markp-fuso Oct 21 2020 at 04:23

Wie derzeit codiert, wurde das Eingabefeldtrennzeichen nicht definiert.

Aktuell:

$ cat myfilter.awk { action_type=$2;
if (action_type=="1") print $0 >> 1_dataset.csv; else if (action_type=="2") print $0 >> 2_dataset.csv;
}

Aufruf:

$ awk -f myfilter.awk dataset.csv

Es gibt verschiedene Möglichkeiten, dies zu beheben:

$ awk -v FS="," -f myfilter.awk dataset.csv

oder

$ cat myfilter.awk BEGIN {FS=","} { action_type=$2
if (action_type=="1") print $0 >> 1_dataset.csv; else if (action_type=="2") print $0 >> 2_dataset.csv;
}

$ awk -f myfilter.awk dataset.csv