Итак, у меня есть набор данных о рейсах в 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]}
}
Но когда я сохраняю это в файл awk и пытаюсь выполнить его с помощью:
решение1
Когда #!/bin/awk
вы говорите awk запуститься с помощьюимяфайла, содержащего скрипт, как скрипт, а не каксодержаниефайла, содержащего скрипт. Это как написать:
awk './delayed_by_day_jan20.awk'
вместо:
awk -f './delayed_by_day_jan20.awk'
Так же, как при указании файла, содержащего скрипт awk, в командной строке, вам -f
также необходимо использовать in shebang, чтобы указать awk открыть переданное ему имя файла (т. е. имя текущего файла скрипта) и использовать его содержимое в качестве интерпретируемого скрипта awk.
Было сказано, что....
Рассматривайте каждую команду, которую вы пишете в Unix, как просто команду. Неважно, написана ли эта команда на awk, perl, shell или чем-то еще - она должна быть названа на основе того, что онаделает, а не как это реализовано. Учитывая это, у вас никогда не должно быть команд, которые заканчиваются на .awk
или .sh
или или .perl
что-либо еще, что указывает на язык, на котором они написаны, чтобы, помимо прочего, вы могли повторно реализовать любую команду, написанную вами в awk, в perl или наоборот, без необходимости проходить через все ваши другие команды, которые вызывают эту команду, чтобы изменить их. Поэтому имя вашей команды должно быть delayed_by_day_jan20
, а не delayed_by_day_jan20.awk
.
Также, другие не согласны с этим, потому что они любят использовать редактор, который понимает синтаксис awk, но IMO вы никогда не должны использовать shebang для вызова awk, просто используйте shebang для вызова любой оболочки, которую вы используете, а затем просто вызовите awk внутри вашего скрипта оболочки, как вы бы вызвали его из командной строки. Это значительно снизит сложность ваших скриптов для тех чрезвычайно распространенных случаев, когда полезно выполнять большую часть работы в awk, но также и ее части в оболочке, например, проверка существования входных файлов, создание временных файлов, установка ловушек, разделение аргументов команды на назначения переменных awk против аргументов awk и т. д. и т. п. Смотритеhttps://stackoverflow.com/a/61002754/1745001игуглите "awk shebang"для получения более подробной информации по этим вопросам.
Вот как написать свой скрипт оболочки:
$ 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 так, чтобы он делал то, что вам нужно, если это не так, и задайте новый вопрос, если у вас возникнут проблемы с этим.