bc不通过脚本执行

时间:2014-04-25 13:21:49

标签: linux bash standard-deviation bc

您好我有一个脚本,用于计算服务器返回的一组值的标准偏差。

我可以轻松地检索命令并使用命令构建有效的字符串。

bc <<< "scale=10; sqrt((0+((782636-782030)^2)+((781460-782030)^2)+((782492-782030)^2)+((781704-782030)^2)+((781860-782030)^2))/5)"

我通过迭代数组并将其附加到字符串来创建此命令。

CMD='bc <<< "scale=10; sqrt((0'
for i in "${MEMORY[@]}"; do
    CMD=$CMD'+(('$i'-'$MEAN')^2)'
done;
CMD=$CMD')/5)"'

一旦我完成了这个,然后尝试将命令字符串执行到变量

SD=`$CMD`   
echo $SD

但是我得到了输出

File <<< is unavailable.

任何想法?

3 个答案:

答案 0 :(得分:4)

<<<需要由shell解析,这在参数扩展之前发生。当您尝试执行

SD=`$CMD`

$CMD中的字符串未被重新分析,因此<<<被视为文字字符串,并作为参数传递给bc。你需要像

这样的东西
BC_EXPRESSION='scale=10; sqrt((0'
for i in "${MEMORY[@]}"; do
    BC_EXPRESSION+="+(($i-$MEAN)^2)"
done
BC_EXPRESSION+=')/5)'

SD=$( bc <<< "$BC_EXPRESSION" )

答案 1 :(得分:2)

您应该在字符串中构建bc命令,然后将此字符串传递给bc

如果我理解正确,你有一组数字memory 1 和一个变量mean,你想要计算memory的标准差(在哪里,我猜,meanmemory)的平均值。

您需要构建(X-mean)^2形式的字符串:

sum_terms=0
for i in "${memory[@]}"; do
    sum_terms+="+(($i)-($mean))^2"
done

此时,字符串sum_terms包含扩展为类似的字符串:

0+((m1)-(mean))^2+((m2)-(mean))^2+ ... +((mn)-(mean))^2

最后,您希望将其括在括号中,添加sqrt(并附加/5)并将其传递给bc

bc <<< "sqrt(($sum_terms)/5)"

一体化:

sum_terms=0
for i in "${memory[@]}"; do
    sum_terms+="+(($i)-($mean))^2"
done
bc -l <<< "sqrt(($sum_terms)/5)"

请注意,我将$mean括号括在括号中,以防这是一个负数(否则会与前面的负号冲突) - 当我在它的时候,我也附上了{{括号中的1}}术语。


作为旁注,您还可以使用$i来计算标准偏差,并以更通用的方式进行:

给定数组E((X-E(X))^2)=E(X^2)-E(X)^2,计算其标准偏差:

memory

事实上,你真的不需要明确的memory=( 782636 781460 782492 781704 781860 ) sum_mem=0 sum_memsq=0 for i in "${memory[@]}"; do sum_mem+="+($i)" sum_memsq+="+($i)^2" done mean=$(bc -l <<< "($sum_mem)/${#memory[@]}") bc -l <<< "sqrt(($sum_memsq)/${#memory[@]}-($mean)^2)" 循环,你可以让for为你完成工作:

printf

1 让我小写所有变量名,大写变量名被认为是不好的做法

答案 2 :(得分:0)

请尝试:

echo "scale=10; sqrt((0+((782636-782030)^2)+((781460-782030)^2)+((782492-782030)^2)+((781704-782030)^2)+((781860-782030)^2))/5)" | bc -l 

即。 echo您的字符串并将输出传递给bc -l

这将有效