set -e
или set -o errexit
не применяется к командам, которые являются частью условий, как в:
if cmd; do
until cmd; do
while cmd; do
cmd || whatever
cmd && whatever
Это относится и к ловушке ERR
для поддерживающих ее снарядов.
Итак, идиоматический способ игнорировать неудачу команды —:
cmd || : errors ignored
Или просто:
cmd || true
cmd || :
Это отменяет set -e
для этого cmd
вызова, а также устанавливает $?
на 0 (на значение :
/ true
, когда cmd
терпит неудачу)
cmd && true
ret=$?
Также отменяет set -e
, но сохраняет статус выхода cmd
.
В одну сторону:
sort -k4n,4 file | awk '$2>=43808877 && $2<=43808882{tot+=$4;cnt++;max=$4;min=cnt==1?$4:min}END{print min, max,tot/cnt}'
Во-первых, мы sort
файл на 4-м столбце, чтобы 1-я запись имела мин, а последняя макс. Используя awk
, мы суммируем числа в диапазоне и печатаем статистику
В этом случае кажется целесообразным разделить задачу на 2 процесса :один для выбора записей с учетом диапазона в 2 доллара, второй для генерации статистики:
awk '43808877 <= $2 && $2 <= 43808882' file |
awk '
NR == 1 {min = max = $4}
$4 < min {min = $4}
$4 > max {max = $4}
{sum += $4}
END {
if (NR) printf "%d\n%d\n%f\n", min, max, sum / NR
}
'
Урезанная версия.
$ awk '/43808877/,/43808882/{t+=$4;c++;if($4>x){x=$4}if($4<n||!length(n)){n=$4}}END{print x,n,t/c}' f
14 3 8.83333
$
$ cat tst.awk
$2>=43808877 && $2<=43808882 {
cnt++
sum += $4
min = ( (cnt == 1) || ($4 < min) ? $4 : min )
max = ( (cnt == 1) || ($4 > max) ? $4 : max )
}
END {
print max+0
print min+0
print (cnt ? sum / cnt : 0)
}
$ awk -f tst.awk file
14
3
8.83333
Обратите внимание на защиту в разделе END, чтобы убедиться, что вы всегда получаете числовой вывод и не получаете ошибку деления на ноль, даже если в нужном диапазоне нет записей.
Если вы не женаты на awk, то Миллер хорош для таких вещей:
mlr --nidx --repifs filter '$2 >= 43808877 && $2 <= 43808882' then stats1 -f 4 -a max,min,mean file