在shell脚本中正确使用bc?

时间:2015-06-24 18:45:30

标签: bash shell math bc

我只想尝试使用bc:

乘以一些浮点变量
#!/bin/bash

a=2.77 | bc
b=2.0  | bc

for cc in $(seq 0. 0.001 0.02)
do
    c=${cc} | bc
    d=$((a * b * c)) | bc
    echo "$d" | bc
done

这并没有给我一个输出。我知道这是一个愚蠢的,但我已经尝试了一些bc的组合(在不同的地方管道等)无济于事。

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:5)

bc是一个命令行实用程序,而不是shell语法的一些模糊部分。该实用程序从其标准输入中读取数学表达式,并将值打印到其标准输出。由于它不是shell的一部分,因此无法访问shell变量。

shell管道运算符( | )将一个shell命令的标准输出连接到另一个shell命令的标准输入。例如,您可以使用管道左侧的bc实用程序将表达式发送到echo

echo 2+2 | bc

这将打印4,因为这里没有比眼睛更好的了。

所以我想你想这样做:

a=2.77
b=2.0
for c in $(seq 0. 0.001 0.02); do
  echo "$a * $b * $c" | bc
done

注意:当shell将参数处理为echo时,会发生shell变量的扩展,因为您可以通过取消bc来验证:

a=2.77
b=2.0
for c in $(seq 0. 0.001 0.02); do
  echo -n "$a * $b * $c" =
  echo "$a * $b * $c" | bc
done

所以bc只看到数字。

如果要将bc的输出保存在变量中而不是将其发送到标准输出(即控制台),则可以使用正常的命令替换语法来执行此操作:

a=2.77
b=2.0
for c in $(seq 0. 0.001 0.02); do
  d=$(echo "$a * $b * $c" | bc)
  echo "$d"
done

答案 1 :(得分:0)

直接将两个数字相乘,您可以执行以下操作:

echo 2.77 * 2.0 | bc

它会产生 2 个位置的结果 - 因子的最大数量。要将其传送到更多位置(例如 5 个),需要:

echo "scale = 5; 2.77 * 2.0" | bc

如果您要乘以每个都有大量小数位的数字,这将变得更加重要。

如其他回复所述,bc 不是 bash 的一部分,而是由 bash 运行的命令。因此,您实际上是直接向命令发送输入——这就是您需要 echo 的原因。如果你把它放在一个文件中(命名为“a”),那么你会运行“bc < a”。或者,您可以将输入直接in 放在shell 脚本中,并让命令运行指定的段作为其输入;像这样:

cat <<EOF
Input
EOF

... 带有限定符(例如,您需要将 "" 写为 "\")。

控制流结构在 BC 中脱离命令行运行可能会更成问题。我尝试了以下

echo "scale = 6; a = 2.77; b = 2.0; define f(cc) { auto c, d; c = cc; d = a*b*c; return d; } f(0); f(0.001); f(0.02)" | bc

并且出现语法错误(我安装了一个 GNU-BC 版本)。另一方面,它会与 C-BC 一起运行

echo "scale = 6; a = 2.77; b = 2.0; define f(cc) { auto c, d; c = cc; d = a * b * c; return d; } f(0); f(0.001); f(0.02)" | cbc

并为您提供预期的结果 - 匹配您引用的示例......将数字列出到 6 个位置。

C-BC 在这里(它在操作上是 GNU-BC 和 UNIX BC 的大型超集,但不是 100% 符合 POSIX):

https://github.com/RockBrentwood/CBC

语法更接近C,所以你也可以写成

echo "scale = 6, a = 2.77, b = 2.0; define f(cc) { return a * b * cc; } f(0); f(0.001); f(0.02)" | cbc

得到相同的结果。所以,再举一个例子,这个

echo "scale = 100; for (x = 0, y = 1; x < 50; y *= ++x); y" | cbc

会给你 50 阶乘。但是,POSIX 不要求 bc 使用逗号表达式,例如 (x = 0, y = 1),因此它不会在其他 bc 方言中运行,例如 GNU BC。