Чтение, хранение и доступ к временным файлам (BASH)
Я хочу загрузить временные файлы с кучей чисел из входного файла. Формат этого скрипта: "testing -row/-col [входной файл]". Входной файл в основном просто набор случайных чисел, таких как
1 2 3 4
3 3 5 6
9 4 4 2
Мой код ниже пытается получить этот входной файл в качестве аргумента, а затем "кошачьи" эти числа в новые временные файлы. Оттуда я пытаюсь найти среднее значение строки из этих временных файлов.
FILENAME=$2
TMP=./TMP2.$$
cat $FILENAME > $TMP
#average row
function avg_row {
while read -a row
do
total=0
sum=0
for i in "${rows[@]}"
do
eum=`expr $sum + $i`
total=`expr $total + 1`
done
average=`expr $sum / $total`
echo $average
done < $TMP
}
Тем не менее, даже если я "перехватываю" файлы TMP, они отображаются точно так же, как и test_file, когда я запускаю скрипт, он печатает
expr: division by zero
expr: division by zero
expr: division by zero
Любые предложения или идеи о том, почему это может произойти? Спасибо.
1 ответ
Два вопроса:
Ваша функция читает в массиве
row
но затем пытается получить доступ к несуществующему массивуrows
, Так какrows
не имеет записей,total
никогда не увеличивается, и деление делится на ноль.Эта линия обновлений
eum
неsum
:eum=`expr $sum + $i`
Кроме того, неясно, почему содержимое $FILENAME копируется перед прочтением. Я предполагаю, что у вас есть веская причина для этого.
Исправленная функция выглядит так:
function avg_row {
while read -a row
do
total=0
sum=0
for i in "${row[@]}"
do
sum=`expr $sum + $i`
total=`expr $total + 1`
done
average=`expr $sum / $total`
echo $average
done < $TMP
Это производит вывод:
$ avg_row
2
4
4
Модернизированная версия Bash
Оба клюшки и expr
архаичны Более современная версия функции bash:
avg_row2() {
while read -a row
do
sum=0
for i in "${row[@]}"
do
((sum += i))
done
echo $((sum / ${#row[@]}))
done < $TMP
}
Это дает тот же результат, что и раньше:
$ avg_row2
2
4
4
версия awk
То же самое можно сделать в awk:
$ awk '{s=0; for (i=1;i<=NF;i++) s+=$i; print int(s/NF);}' filename
2
4
4
В отличие от bash, awk может выполнять арифметику с плавающей запятой:
$ awk '{s=0; for (i=1;i<=NF;i++) s+=$i; print s/NF;}' filename
2.5
4.25
4.75