Арифметика с элементами массива в bash

Я использую bash и пытаюсь добавить все элементы массива, созданного из файла.

while read line; do
    array=($line);
    sum=0
    length=${#array[@]}
    for i in ${array[@]:0:$length}; do
       sum=$[$sum+${array[i]}]   #<--- this doesn't work?
    done
    echo $sum
done < $1

редактировать: мне должно было быть яснее, почему я хочу использовать разбиение массива в цикле for

Ввод может быть ------> david 34 28 9 12

И я хочу напечатать ---> david 83

Итак, я хотел бы перебрать все элементы, приняв первый. поэтому я бы использовал:

length=$[${#array[@]} - 1]
for i in${array[@]:1:$length}

из-за этого я не могу использовать:

for i in "${array[@]}"

person Vaderico    schedule 29.03.2015    source источник


Ответы (2)


Попробуйте использовать expr, чтобы добавить два выражения, например:

sum=$(expr "$sum" + "${arr[i]}")

Or

sum=$((sum + arr[i]))


echo "11 13" >test.txt 
echo "12" >>test.txt

while read -a line; do ##read it as array
    sum=0
    for ((i=1; i < ${#line}; i++)); do ##for every number in line
       sum=$(expr "$sum" + "${line[i]}") ## add it to sum
    done
    echo $line[0] $sum ##print sum
done < test.txt
Output
36

После редактирования ОП:

echo "ABC 11 13" >test.txt echo "DEF 12" >>test.txt

while read -a line; do ##read it as array
sum=0
for ((i=1; i < $((${#line[@]})); i++)); do ##for every number in line
   sum=$(expr "$sum" + "${line[i]}") ## add it to sum
   if [[ $i -eq $((${#line[@]}-1)) ]]
   then
       echo "${line[0]} $sum" ##print sum
       sum=0
   fi
done
done < test.txt
Output:
ABC 24
DEF 12
person SMA    schedule 29.03.2015
comment
sum=$(expr $sum + ${arr[i]}) : выдает ошибку. sum=$((sum + arr[i])) : не работает :/ и не выдает ошибки - person Vaderico; 29.03.2015
comment
Я изменил ваш сценарий. - person SMA; 29.03.2015
comment
Я не могу использовать этот цикл for, я объясню, почему в отредактированном вопросе. - person Vaderico; 29.03.2015
comment
как насчет for i in "${!line[@]}"; do или for ((i=0; i < ${#line}; i++)) или for ((i=0; i < ${length}; i++)) Также не продолжайте редактировать вопрос с дополнительными требованиями. - person SMA; 29.03.2015
comment
Проблема не в цикле, я успешно перебираю от индекса 1 до длины массива. Проблема только в арифметике. Он не принимает добавление целого числа и номера строки массива. - person Vaderico; 29.03.2015
comment
хорошо, это тоже работает, спасибо за помощь! очень признателен - person Vaderico; 29.03.2015

Если вы хотите суммировать числа в каждой строке файла, используя цикл в bash, вы можете сделать

#!/bin/bash
while read line; do
    array=($line);
    sum=0
    length=${#array[@]}
    for i in ${array[@]:0:$length}; do
       sum=$[$sum+$i]
    done
    echo $sum
done < "$1"

Разница с вашим кодом в том, что i является элементом в массиве, а не индексом.

Однако хранение файлов в bash происходит довольно медленно. Вероятно, вам было бы лучше выполнить задачу в awk, например, вот так:

awk '{s=0;for(i=1;i<=NF;i++) s+=$i;print s}' file
person user000001    schedule 29.03.2015
comment
Я не могу использовать этот цикл for, я объясню, почему в отредактированном вопросе. - person Vaderico; 29.03.2015
comment
@Vderico Тем не менее i - это значение, а не индекс. См. редактирование. Также у вас опечатка в вопросе. Должно быть length=${#array[@]}, а не length=${#arr[@]} - person user000001; 29.03.2015