15

我正在尝试添加由read -a命令的用户输入定义的数组元素。我怎样才能做到这一点?

4

9 回答 9

26
read -a array
tot=0
for i in ${array[@]}; do
  let tot+=$i
done
echo "Total: $tot"
于 2012-11-29T21:50:45.747 回答
20

给定一个(整数)数组,这是一种添加其元素的有趣方法(在 bash 中):

sum=$(IFS=+; echo "$((${array[*]}))")
echo "Sum=$sum"

例如,

$ array=( 1337 -13 -666 -208 -408 )
$ sum=$(IFS=+; echo "$((${array[*]}))")
$ echo "$sum"
42

优点:没有循环,没有 subshel​​l!

缺点:仅适用于整数

编辑 (2012/12/26)。

随着这篇文章的出现,我想与您分享另一种有趣的方式,使用dc,它不仅限于整数:

$ dc <<< '[+]sa[z2!>az2!>b]sb1 2 3 4 5 6 6 5 4 3 2 1lbxp'
42

这条奇妙的线将所有数字相加。整齐,嗯?

如果您的号码在数组中array

$ array=( 1 2 3 4 5 6 6 5 4 3 2 1 )
$ dc <<< '[+]sa[z2!>az2!>b]sb'"${array[*]}lbxp"
42

事实上,负数有一个问题。数字 '-42' 应该被赋予dcas _42,所以:

$ array=( -1.75 -2.75 -3.75 -4.75 -5.75 -6.75 -7.75 -8.75 )
$ dc <<< '[+]sa[z2!>az2!>b]sb'"${array[*]//-/_}lbxp"
-42.00

会做。

优点:适用于浮点数。

缺点:使用外部进程(但如果您想进行非整数运算,则别无选择 - 但dc可能是此任务中最轻的)。

于 2012-11-29T22:01:35.427 回答
8

我的代码(我实际使用的)受到gniourf_gniourf答案的启发。我个人认为这更易于阅读/理解和修改。也接受浮点数,而不仅仅是整数。

对数组中的值求和:

arr=( 1 2 3 4 5 6 7 8 9 10 )
IFS='+' sum=$(echo "scale=1;${arr[*]}"|bc)
echo $sum # 55

只需稍加改动,即可得到平均值:

arr=( 1 2 3 4 5 6 7 8 9 10 )
IFS='+' avg=$(echo "scale=1;(${arr[*]})/${#arr[@]}"|bc)
echo $avg # 5.5
于 2015-07-27T12:42:12.977 回答
6

gniourf_gniourf 的答案非常好,因为它不需要循环或 bc。对于任何对真实示例感兴趣的人,这里有一个函数可以汇总从 /proc/cpuinfo 读取的所有 CPU 内核,而不会弄乱 IFS:

# Insert each processor core count integer into array
cpuarray=($(grep cores /proc/cpuinfo | awk '{print $4}'))
# Read from the array and replace the delimiter with "+"
# also insert 0 on the end of the array so the syntax is correct and not ending on a "+"
read <<< "${cpuarray[@]/%/+}0"
# Add the integers together and assign output to $corecount variable
corecount="$((REPLY))"
# Echo total core count
echo "Total cores: $corecount"

我还发现从双括号内调用数组时算术扩展工作正常,无需读取命令:

cpuarray=($(grep cores /proc/cpuinfo | awk '{print $4}'))
corecount="$((${cpuarray[@]/%/+}0))"
echo "Total cores: $corecount"

通用的:

array=( 1 2 3 4 5 )
sum="$((${array[@]/%/+}0))"
echo "Total: $sum"
于 2018-01-26T16:06:36.450 回答
5

我喜欢简洁,所以这是我倾向于使用的:

IFS="+";bc<<<"${array[*]}"

它本质上只是列出了数组的数据并将其传递给 BC 来评估它。“IFS”是内部字段分隔,它本质上是指定如何分隔数组,我们说用加号分隔它们,也就是说当我们将它传递给BC时,它会收到一个由加号分隔的数字列表,所以很自然它将它们加在一起。

于 2015-11-04T19:31:07.583 回答
2

另一种dc&bash方法:

arr=(1 3.88 7.1 -1)
dc -e "0 ${arr[*]/-/_} ${arr[*]/*/+} p"

输出:

10.98

0 1 3.88 7.1 _1 + + + + p上面用运行表达式dc。请注意虚拟值0,因为 s 太多了+,还请注意通常的负数前缀-必须更改为_in dc

于 2018-01-26T19:14:14.753 回答
1
arr=(1 2 3) //or use `read` to fill the array
echo Sum of array elements: $(( ${arr[@]/%/ +} 0))
Sum of array elements: 6

解释:

  1. "${arr[@]/%/ +}"将返回1 + 2 + 3 +
  2. 通过在最后添加额外的零,我们将得到1 + 2 + 3 + 0
  3. 通过像这样用 BASH 的数学运算包装这个字符串$(( "${arr[@]/%/ +} 0")),它将返回总和

这可以用于其他数学运算。

  1. 对于减去只是-使用
  2. 用于乘法*1而不是0

也可以与逻辑运算符一起使用。

  1. 布尔和示例 - 检查所有项目是否为真 (1)

    arr=(1 0 1)

    if [[ $((${arr[@]/%/ &} 1)) -eq 1 ]]; then echo "yes"; else echo "no"; fi

    这将打印:否

  2. 布尔或示例 - 检查任何项目是否为真 (1)

    arr=(1 0 0)

    if [[ $((${arr[@]/%/ |} 0)) -eq 1 ]]; then echo "yes"; else echo "no"; fi

    这将打印:是

于 2021-07-30T16:09:11.027 回答
0

我发现使用递增变量非常简单:

result2=0
for i  in ${lineCoffset[@]};
do
    result2=$((result2+i))  
done
echo $result2
于 2017-02-21T16:01:31.610 回答
0

一个简单的方法

function arraySum 
{
        sum=0
        for i in ${a[@]};
        do
              sum=`expr $sum + $i`  
        done
        echo $sum
}

a=(7 2 3 9)
echo -n "Sum is = " 
arraySum ${a[@]}
于 2019-03-11T11:22:09.233 回答