将Bash表达式传递给AWK进行浮点数算术运算

3

我试图在Bash中进行浮点数算术运算,但是由于不支持浮点数,因此尝试使用AWK来解决问题。以下是我面临的问题:

我发现以下代码对我有效:

代码

echo - | awk '{printf("%04.4f \n", (-225.2*7+30*6)/17 + (19^2)/9) }'

输出

-42.0301

但我的目的是"读取表达式"并计算值,精确到小数点后4位,因此尝试了下面的代码输入相同的表达式(-225.2*7+30*6)/17 + (19^2)/9),它给出了不正确的值(我猜变量被传递为字符串到awk):

代码

read inpt 
echo - | awk -v input=$inpt '{printf("%04.4f \n", input) }'

输出

0.0000

注意:请忽略此示例表达式中第二个 + 符号周围的空格,可以使用 sed 或类似方法来删除它(如果带有空格,则在从 bash 传递变量时,awk 将出现语法错误)。

非常感谢任何帮助。提前致谢。

PS:我的 bash 版本是“bash-4.2”。我想这就是阻止我使用许多其他选项的 bash 版本。


Bash 版本不会影响外部命令的可用性。获取 bc 的访问权限可能只需要执行 sudo apt install -y bc 或者相应平台的等效操作即可。 - tripleee
4个回答

4

在awk中,你不能直接评估变量中的数据。在这种情况下,你需要编写一个算术求值器或使用现有的求值器,比如https://github.com/radare/radare2-bindings/blob/master/awk/calc.awk。一旦你修复了缺失的括号并正确引用了表达式,你就可以:

$ echo "((-225.2*7+30*6)/17 + (19^2)/9)" | awk -f calc.awk
((-225.2*7+30*6)/17 + (19^2)/9) =        -42.0301

或者您可以将其直接传输到 bc,同时设置所需的精度(scale)。 - Anubis
1
在另一个已被删除的回答的评论中,提问者提到他不能使用 bc - James Brown

1
我推荐并点赞James Brown的回答。但是,如果你需要立即使用而且不需要外部依赖,你可以简单地将输入插入到脚本中。
awk "END { printf("%04.4f\n", $input) }" </dev/null

这与使用eval的功能等效,因此如果您不知道可以信任输入的部署位置(例如,因为它来自受控进程而不是实际用户),则需要执行某种形式的净化(即使如此,如果输入不是格式良好的Awk表达式,则可能会遇到奇怪或明显误导性的错误消息)。
read -p "Input an Awk expression: " input
case $input in
  *[!-+/*()^%0-9]*)
    echo "$0: invalid input" >&2
    exit 1;;
esac
awk ...

注意到避免基本无用的echo的构造。从/dev/null重定向输入并将代码放在END(或BEGIN)块中是运行任意一段Awk脚本的标准技术,不需要任何输入。

0

首先,我认为命令没有任何问题,应该可以运行。如果问题仍然存在,请尝试重新输入精确的命令,并提供详细信息。

但是,如果您只需要格式化输出,可以直接使用 printf 命令。

$ read input
12.34
$ printf '%4.4f' $input
12.3400

编辑:

如果您需要在执行某些计算后格式化输出,则可以选择使用bc。(awk仍然有效)

$ echo "scale=4; (-225.2*7+30*6)/17+(19^2)/9" | bc
-42.0300

你可以像平常一样在表达式中使用变量。

$ read inpt
1234
$ echo "scale=4; $inpt * 0.01" | bc
12.34

实际上,我需要评估表达式而不仅仅是打印浮点数。我在常规的Bash脚本中没有看到它工作。它可以在awk中工作,但我无法将浮点表达式变量从bash传递到awk构造中。 - PRD
好的,我说过你尝试的东西没有什么问题。但因为我也(就像另一个答案里说的)是bc的爱好者,我会做一些像下面这样的事情: echo "scale=4; (-225.2*7+30*6)/17+(19^2)/9" | bc 或者使用 read 输入 echo "scale=4; $inpt * 12.34" | bc - Anubis

-1

这是你在寻找的吗?

 echo "25 50"| awk '{print $2,"/",$1}' | bc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接