如何在shell脚本中计算值?

jok*_*ino 4 bash arithmetic bc

我在终端中运行此命令:

grep "bla bla blah" blah* | echo "Blah: $(wc -l) / $(ls | wc -l) * 100"
Run Code Online (Sandbox Code Playgroud)

我得到这个输出:

Blah: 44 / 89 * 100
Run Code Online (Sandbox Code Playgroud)

我期望看到什么:

49.4
Run Code Online (Sandbox Code Playgroud)

有没有办法仅使用 bash 命令来获得所需的输出?我不喜欢我计划通过管道输出的脚本。

Gil*_*il' 5

你的代码说要打印一个字符串。它没有在任何地方表明该字符串实际上是您想要计算的算术表达式。所以你不能合理地期望你的表达式被评估。

您的代码不是最优的。$(wc -l)将计算 所返回的匹配数grep,但有一种更简单的方法:grep -c改为运行。$(ls | wc -l)是计算当前目录中非点文件的不可靠方法,因为的输出ls不可靠$(set -- *; echo $#)是执行此操作的一种可靠方法(假设至少有一个匹配文件;如果该假设可能不成立,请使用$(set -- *; if [ -e "$1" ]; then echo $#; else echo 0; fi,但请注意,这将导致除以零,低于该值您应该以某种方式将其视为错误条件)。所以你可以这样编写你的代码:

matches=$(grep -c "bla bla blah" blah*)
files=$(set -- *; echo $#)
echo "Blah: $matches / $files * 100"
Run Code Online (Sandbox Code Playgroud)

或者您可以内联两个中间值的计算:

echo "Blah: $(grep -c "bla bla blah" blah*) / $(set -- *; echo $#) * 100"
Run Code Online (Sandbox Code Playgroud)

现在,要执行算术运算,您可以使用 shell 的内置算术扩展,但它仅限于整数运算,因此/运算符将向下舍入到最接近的整数。

echo "Blah: $(($matches * 100 / $files))"
Run Code Online (Sandbox Code Playgroud)

在 ksh93、zsh 和 yash 中(但在其他 shell 中除外),如果表达式中存在强制浮点的内容(例如浮点常量),您将获得浮点算术。Bourne shell、ksh88、pdksh、bash、ash 中不存在此功能。

echo "Blah: $(($matches * 100.0 / $files))"
Run Code Online (Sandbox Code Playgroud)

bc实用程序以任意精度对十进制数执行运算。

echo "Blah: $(echo "scale=2; $matches * 100 / $files" | bc)"
Run Code Online (Sandbox Code Playgroud)

另一个可以执行浮点计算(可用的数学函数较少)的标准实用程序是awk

echo "$matches" "$files" | awk '{print "Blah:", $1 * 100 / $2}'
Run Code Online (Sandbox Code Playgroud)