在 shell 脚本中正确使用 bc?

Correct usage of bc in a shell script?

我只是想用 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 的多种组合(在不同的地方等)无济于事。

如有任何帮助,我们将不胜感激!

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

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

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 变量的扩展发生在 shell 处理 echo 的参数时,您可以通过省略 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

要将两个数字 直接相乘 ,您可以这样做:

echo 2.77 * 2.0 | bc

它会产生一个结果到2个地方-因素最多的地方。要让它到达更多的地方,比如 5 个,需要:

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

如果您要乘以小数位数较多的数字,这一点就变得更加重要。

如其他回复所述,bc 不是 bash 的一部分,而是 bash 的命令 运行。因此,您实际上是将输入 直接 发送到命令 - 这就是您需要 echo 的原因。如果你把它放在一个文件中(命名为“a”),那么你会 运行 “bc < a”。或者,您可以直接将输入 放入 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阶乘。但是,逗号表达式,例如 (x = 0, y = 1) 并不是 POSIX 对 bc 强制要求的,因此它不会 运行 在其他 bc 方言中,例如 GNU BC。