awk gibt den Prozentsatz nach Wochentag zurück

awk gibt den Prozentsatz nach Wochentag zurück

Ich habe also einen Datensatz mit Flügen in einer CSV-Datei und möchte den Prozentsatz der verspäteten Flüge (Spalte 6) nach Tagen sortiert erhalten. 0 steht für keine Verspätung und 1 für eine Verspätung von 15 oder mehr Minuten.

Eingang:

DAY_OF_MONTH,"DAY_OF_WEEK","ORIGIN","DEST","DEP_TIME","DEP_DEL15","CANCELLED","DIVERTED","DISTANCE"
1,Tuesday,ORD,GRB,1003,0.00,0.00,0.00,322.248
1,Tuesday,TUL,ORD,1027,0.00,0.00,0.00,1083.42
1,Tuesday,EWR,TYS,1848,0.00,0.00,0.00,1168.61

Ausgabe:

Weekday, % delayed, delayed, total flights
Tuesday,0.00,0,3

Der Datensatz verfügt tatsächlich über viele Zeilen und enthält jeden Tag eines Monats und alle dazugehörigen Flüge. Dies wäre also nicht die tatsächliche Ausgabe.

Jemand hat mir dabei geholfen, Folgendes zu finden:

#!/bin/awk
BEGIN { FS = OFS = "," }
FNR > 1 { total[$2]++; if ($6) delay[$2]++ }
END {
    print "\"weekday\"", "\"percentage_delayed\"", "\"delayed\"", "\"total_flights\""
    for ( day in total ) { print day, delay[day] / total[day] * 100, delay[day], total[day]}

}

Aber wenn ich dies in einer Awk-Datei speichere und versuche, es mit folgendem auszuführen:Terminal-Ausgabe

Antwort1

Mit #!/bin/awksagen Sie awk, es soll mit demNameder Datei, die das Skript enthält, als Skript und nicht alsInhaltder Datei, die das Skript enthält. Das ist, als würde man schreiben:

awk './delayed_by_day_jan20.awk'

anstatt:

awk -f './delayed_by_day_jan20.awk'    

Genau wie beim Angeben einer Datei, die ein Awk-Skript in der Befehlszeile enthält, müssen Sie -fauch in einem Shebang awk anweisen, den übergebenen Dateinamen (also den Namen der aktuellen Skriptdatei) zu öffnen und dessen Inhalt als zu interpretierendes Awk-Skript zu verwenden.

Nachdem das gesagt ist...

Betrachten Sie jeden Befehl, den Sie in Unix schreiben, als bloßen Befehl. Es spielt keine Rolle, ob dieser Befehl in awk, perl, shell oder sonst etwas geschrieben ist - er sollte basierend auf dem benannt werden, was ertut, nicht wie es implementiert ist. Aus diesem Grund sollten Sie niemals Befehle verwenden, die mit .awkoder .shoder .perloder irgendetwas anderem enden, das auf die Sprache hinweist, in der sie geschrieben sind, sodass Sie unter anderem jeden Befehl, den Sie in awk geschrieben haben, in Perl oder umgekehrt neu implementieren können, ohne alle Ihre anderen Befehle, die diesen Befehl aufrufen, durchgehen zu müssen, um sie zu ändern. Ihr Befehlsname sollte also lauten delayed_by_day_jan20, nicht delayed_by_day_jan20.awk.

Andere sind damit auch nicht einverstanden, weil sie lieber einen Editor verwenden, der die AWK-Syntax versteht, aber meiner Meinung nach sollten Sie niemals ein Shebang verwenden, um AWK aufzurufen. Verwenden Sie einfach das Shebang, um die von Ihnen verwendete Shell aufzurufen, und rufen Sie dann einfach AWK in Ihrem Shell-Skript auf, so wie Sie es von der Befehlszeile aus aufrufen würden. Das wird die Komplexität Ihrer Skripte in den äußerst häufigen Fällen erheblich reduzieren, in denen es nützlich ist, den Großteil der Arbeit in AWK, aber auch Teile davon in der Shell zu erledigen, z. B. das Überprüfen der Existenz von Eingabedateien, das Erstellen temporärer Dateien, das Setzen von Traps, das Trennen von Befehlsargumenten in AWK-Variablenzuweisungen vs. AWK-Argumente usw. usw. Siehehttps://stackoverflow.com/a/61002754/1745001Undgoogle "oh Sch***"für weitere Informationen zu den Problemen.

So schreiben Sie Ihr Shell-Skript:

$ cat delayed_by_day_jan20
#!/usr/bin/env bash

awk '
BEGIN { FS = OFS = "," }
FNR > 1 { total[$2]++; if ($6) delay[$2]++ }
END {
    print "\"weekday\"", "\"percentage_delayed\"", "\"delayed\"", "\"total_flights\""
    for ( day in total ) {
        printf "%s,%0.2f,%d,%d\n", day, delay[day] / total[day] * 100, delay[day], total[day]
    }
}
' "${@:--}"

$ ./delayed_by_day_jan20 file
"weekday","percentage_delayed","delayed","total_flights"
Tuesday,0.00,0,3

Korrigieren Sie jetzt einfach Ihr Awk-Skript, sodass es das tut, was Sie möchten, falls es das nicht kann, und stellen Sie eine neue Frage, wenn dabei Probleme auftreten.

verwandte Informationen