我想在shell中计算一个表达式。我使用以下代码:
pi=$(echo "scale=10; 4*a(1)" | bc -l)
i=3
d=`expr (1+c($pi*($i/10)+$pi))/2 | bc -l`
但它说
bad pattern: (1+c(3.1415926532*(3/10)+3.1415926532))/2
为什么?
答案1
因为您在上一个命令中使用的expr
地方可能应该使用echo
.
$(…)
PS 我建议您在两个命令中使用该形式bc
(而不是`…`
)。
答案2
请注意,设置比例的位置会对计算产生影响。
这个脚本:
bc -l << \EOF
scale = 10
pi = 4 * a(1)
i = 3
(1 + c(pi * (i / 10) + pi)) / 2
EOF
bc -l << \EOF
pi = 4 * a(1)
i = 3
scale = 10
(1 + c(pi * (i / 10) + pi)) / 2
EOF
bc -l << \EOF
pi = 4 * a(1)
i = 3
r = (1 + c(pi * (i / 10) + pi)) / 2
scale = 10
r/1
EOF
bc -l << \EOF
scale = 100
pi = 4 * a(1)
i = 3
r = (1 + c(pi * (i / 10) + pi)) / 2
scale = 15
r/1
EOF
输出:
.2061073736
.2061073739
.2061073738
.206107373853763
答案3
如果你接受我的建议,你就不会使用 `` 或者$()
- 这有点愚蠢。bc
是一个交互式的、面向行的解释器。它从标准输入中读取一行,根据刚刚读取的输入检查是否需要另一行,然后将其结果打印到标准输出或在标准输入上提示更多信息。与您的 shell 一样,它甚至会拒绝执行除行缓冲区输出之外的任何操作,即使它被写入终端以外的其他地方。根本不需要bc
为每个计算调用一个新的 - 特别是在命令替换中还涉及调用一个全新的 shell 并分配一个新的管道。
最好的方法是建立一个协同进程。
# in a bash shell
exec 8<> >( : ) 9< <( bc <&8 )
echo 'b=5;++b' >&8
read b <&9
echo "$b"
6
并且它将bc
继续运行 - 您正在做大量工作以在短暂的、命令替代的进程之间来回穿梭的所有这些变量值bc
可以更容易地集中存储在中央bc
.
echo b\*b >&8; read b <&9; echo "$b"
32
更好的是,因为我前几天学会了如何执行此操作,您可以将bc
进程放在套接字服务器上。
{ ncat -l 9000 --allow localhost -k| bc; } <>/dev/fd/1 |:&
并使用会说该语言的 shell /dev/tcp
:
{ echo 'b=10;b' >&0; read b; echo "$b"; } <>/dev/tcp/localhost/9000
10
这可能会有点麻烦。我写了一个小函数叫做bchat()
让事情变得更容易。
bchat(){
local IFS=\; ### separate on ;
printf ${1+'%s;"\n"\n';}"$*" ### print \0 if no args
set -- ### init args
while read bchat && ### while read <bc
"${bchat:+set}" -- "$@" "${bchat:=$*}" ### append to args
do :; done 2>/dev/null ### and done
} <>"$BC" >&0 ### $BC must be set
如上所示设置套接字服务器后,您可以使用该函数,例如:
BC=/dev/tcp/localhost/9000
bchat b=5 x='(b--)' '"x="' ++x '"b="' --b
echo "$bchat"
x=6;b=3
...再说一遍,只要 bc 进程存在,该状态就会持续存在...