awk Ausgabe in Datei basierend auf Filter
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
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
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
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