Вы сказали «bash built-ins», но ваш скрипт начинается с #!/bin/sh
- который запрашивает POSIX sh, а не bash. Предполагаю, однако, что вы действительно do хотите bash.
#!/bin/bash
[[ -f "$1" ]] || { echo "Not a file" >&2; exit 1; }
exec <"$1"
total=0
while IFS=':' read -r _ _ _ groupid _; do
((total += groupid))
done
echo "$total"
Чтобы объяснить конкретные операции используются для замены компонентов вашего AWK сценария: The read
команды итерации строк (по умолчанию), разделив их символами в IFS
; поэтому IFS=: read -r _ _ _ groupid _
отбрасывает первые три столбца, помещает четвертое место в переменной с именем groupid
и отбрасывает остальное. (())
- математический контекст в bash; внутри него синтаксис C-стиля применим для целочисленных арифметических операций, поэтому добавление.
Кстати, чтение /etc/passwd
непосредственно плохая идея - это не будет работать на системы с использованием LDAP или NIS, или любой другой альтернативной службы каталогов. Если вы на хосте Linux, вы можете использовать программу getent
, чтобы сделать поиск, который работает с любым текущей службой каталогов:
$ yourscript <(getent passwd)
Все, что сказал, предпосылка для этого вопроса является плохой один - - хотя есть накладные расходы для нереста любой внешней программы, включенной awk, когда она работает awk намного, намного быстрее, чем bash. Если бы скорость была вашим единственным приоритетом, вам лучше не использовать оболочку вообще, и ваш скрипт начнется с shebang, который напрямую запускает awk-интерпретатор.
Я думаю, что 'awk -F: '{print s + = $ 4} END {print s}'/etc/passwd' довольно быстро. – fedorqui
Вам действительно нужно делать это столько раз, что производительность родного bash vs awk имеет значение? –
Какое возможное использование для добавления идентификаторов группы вместе? Звучит как плохо разработанное домашнее задание. – chepner