因此,我有一個 CSV 檔案中的航班資料集,我想取得按天排序的延誤航班的百分比(第 6 列)。 0 表示不延遲,1 表示延遲 15 分鐘或以上。
輸入:
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
輸出:
Weekday, % delayed, delayed, total flights
Tuesday,0.00,0,3
該資料集實際上有很多行,並且有一個月中的每一天及其所有航班,因此這不是實際的輸出。
有人幫我想出了:
#!/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]}
}
答案1
當#!/bin/awk
你告訴 awk 使用姓名包含腳本的檔案作為腳本而不是內容包含腳本的檔案的名稱。就像寫:
awk './delayed_by_day_jan20.awk'
代替:
awk -f './delayed_by_day_jan20.awk'
就像在命令列上指定包含 awk 腳本的檔案一樣,您-f
也必須在 shebang 中使用來告訴 awk 開啟它傳遞的檔案名稱(即目前腳本檔案的名稱)並將其內容用作 awk 腳本來解釋。
話說回來....
將您在 Unix 中編寫的每個命令視為只是一個命令。該命令是否以 awk、perl、shell 或其他任何語言編寫並不重要 - 它應該根據它的內容來命名做,而不是它是如何實現的。有鑑於此,您絕對不應該使用以.awk
or.sh
或.perl
或其他任何形式結尾的命令,以指示它們所使用的語言,這樣您就可以將在awk 中編寫的任何命令重新實現為perl,反之亦然,而無需這樣做。所以你的命令名稱應該是delayed_by_day_jan20
,而不是delayed_by_day_jan20.awk
。
另外,其他人不同意這一點,因為他們喜歡使用理解awk 語法的編輯器,但在我看來,你永遠不應該使用shebang 來調用awk,只需使用shebang 來調用你使用的任何shell,然後在你的shell 腳本中簡單地呼叫awk 即可就像您從命令列呼叫它一樣。對於那些極其常見的情況,這將大大降低腳本的複雜性,在這些情況下,在awk 中完成大部分工作很有用,但在shell 中完成部分工作也很有用,例如驗證輸入檔案的存在、創建臨時檔案、設定陷阱、將指令參數分隔為awk 變數賦值與 awk 參數等。https://stackoverflow.com/a/61002754/1745001和谷歌“awk shebang”有關這些問題的更多資訊。
以下是編寫 shell 腳本的方法:
$ 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
現在只需修復您的 awk 腳本以執行您希望它執行的任何操作(如果不是這樣的話),如果您在執行此操作時遇到麻煩,請提出一個新問題。