我正在尝试添加由用户输入定义的数组元素,这是通过 read -a
命令完成的。我该如何实现?
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"
e.g.,
$ array=( 1337 -13 -666 -208 -408 )
$ sum=$(IFS=+; echo "$((${array[*]}))")
$ echo "$sum"
42
优点:无循环,无子shell!
缺点:仅适用于整数
由于此帖被推上来了,我想与您分享另一种有趣的方法,使用 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
dc
,因此:$ 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
可能是最轻量级的工具)。
$(...)
)总是会创建一个子shell。请参见mklement0的答案以及当命令替换比孤立的相同命令产生更多子shell时发生了什么?。 - pjh我的代码(我实际使用的)灵感来自于 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
arr =(1 2 3 4 5 6 7 8 9 10); echo $(IFS ='+'; bc<<<“scale = 1;($ {arr [*] })/ $ {# arr [@]}”)
此外,您可以使用“Here String”而不是echo来保存1个进程。 - Bruno Bronoskygniourf_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时,它会接收由加号分隔的数字列表,因此自然地将它们加在一起。
<<<
符号的用法吗? - Sopalajo de Arrierez另一种 dc
和 bash
方法:
arr=(1 3.88 7.1 -1)
dc -e "0 ${arr[*]/-/_} ${arr[*]/*/+} p"
输出:
10.98
dc
运行表达式 0 1 3.88 7.1 _1 + + + + p
。请注意,由于有一个多余的 +
,所以需要添加虚拟值 0
,同时也要注意在 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
$(( "${arr[@]/%/ +} 0"))
,它将返回总和这可以用于其他数学运算。
-
*
和 1
代替 0
也可以与逻辑运算符一起使用。
布尔AND示例-检查所有项是否为true(1)
arr=(1 0 1)
if [[ $((${arr[@]/%/ &} 1)) -eq 1 ]]; then echo "yes"; else echo "no"; fi
这将打印: no
布尔OR示例-检查任何项是否为true(1)
arr=(1 0 0)
if [[ $((${arr[@]/%/ |} 0)) -eq 1 ]]; then echo "yes"; else echo "no"; fi
这将打印: yes
我觉得使用一个递增变量非常简单:
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[@]}
let
命令可以用于小数吗?我不得不使用total=$(echo "$total + $i" | bc -l)
。 - userABC123