我正在尝试添加由read -a
命令的用户输入定义的数组元素。我怎样才能做到这一点?
9 回答
read -a array
tot=0
for i in ${array[@]}; do
let tot+=$i
done
echo "Total: $tot"
给定一个(整数)数组,这是一种添加其元素的有趣方法(在 bash 中):
sum=$(IFS=+; echo "$((${array[*]}))")
echo "Sum=$sum"
例如,
$ array=( 1337 -13 -666 -208 -408 )
$ sum=$(IFS=+; echo "$((${array[*]}))")
$ echo "$sum"
42
优点:没有循环,没有 subshell!
缺点:仅适用于整数
编辑 (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' 应该被赋予dc
as _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
可能是此任务中最轻的)。
我的代码(我实际使用的)受到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
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"
我喜欢简洁,所以这是我倾向于使用的:
IFS="+";bc<<<"${array[*]}"
它本质上只是列出了数组的数据并将其传递给 BC 来评估它。“IFS”是内部字段分隔,它本质上是指定如何分隔数组,我们说用加号分隔它们,也就是说当我们将它传递给BC时,它会收到一个由加号分隔的数字列表,所以很自然它将它们加在一起。
另一种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
。
arr=(1 2 3) //or use `read` to fill the array
echo Sum of array elements: $(( ${arr[@]/%/ +} 0))
Sum of array elements: 6
解释:
"${arr[@]/%/ +}"
将返回1 + 2 + 3 +
- 通过在最后添加额外的零,我们将得到
1 + 2 + 3 + 0
- 通过像这样用 BASH 的数学运算包装这个字符串
$(( "${arr[@]/%/ +} 0"))
,它将返回总和
这可以用于其他数学运算。
- 对于减去只是
-
使用 - 用于乘法
*
,1
而不是0
也可以与逻辑运算符一起使用。
布尔和示例 - 检查所有项目是否为真 (1)
arr=(1 0 1)
if [[ $((${arr[@]/%/ &} 1)) -eq 1 ]]; then echo "yes"; else echo "no"; fi
这将打印:否
布尔或示例 - 检查任何项目是否为真 (1)
arr=(1 0 0)
if [[ $((${arr[@]/%/ |} 0)) -eq 1 ]]; then echo "yes"; else echo "no"; fi
这将打印:是
我发现使用递增变量非常简单:
result2=0
for i in ${lineCoffset[@]};
do
result2=$((result2+i))
done
echo $result2
一个简单的方法
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[@]}