awk 或 perl 来评估每行中的数学表达式

awk 或 perl 来评估每行中的数学表达式

我想要一个脚本使 awk 成为一个交互式数学计算器,以评估每行中给出的数学表达式。

即,不要构造 awk 命令来计算如下所示的表达式:

$ awk 'BEGIN{print 180/1149}'
0.156658

$ awk 'BEGIN{print (150+141)/1149}'
0.253264

我希望我的脚本将我的数学表达式作为输入并交互式地进行计算。因此会话将如下所示(输入和输出的替代):

180/1149
0.156658
(150+141)/1149
0.253264
1 + 2
3
2 * 3 - 5
1

但是我自己无法做到这一点:

$ awk '{print}'
180/1149
180/1149
^C

$ awk '{print $0}'
180/1149
180/1149
1 + 2
1 + 2
^C

如果 awk 没有简单的解决方案,还有什么,比如 perl?

答案1

算术评估是作为awk/perl语言评估的一部分完成的。perl有一个eval在运行时将任意字符串评估为 perl 代码,所以你可以这样做:

perl -lne 'print eval $_'

awk事实并非如此(尽管在 GNU 的情况下awk,它的调试器会这样做,请参见下文),因此您需要awk为每一行输入运行,并在代码参数中传递该行的内容,例如使用 GNU xargs

xargs -rd '\n' -I CODE awk -- 'BEGIN{print(CODE)}'

你还可以这样做:

sed 's/.*/BEGIN{print(&)}/' | awk -f -

运行一个awk来解释所有代码行,但awk只会在到达输入末尾时开始对其进行评估,因此不能交互使用。不过,您可以重复使用过去评估的结果perl。喜欢:

a = 3+4
a*2

7那么它就会打印出来14


使用 gawk 的调试器

awk有一个调试器模式,eval您可以将 awk 代码传递给该模式进行解释,因此您可以使用以下命令劫持它:

sed -u 's/["\\]/\\&/g;s/.*/eval "print(&)"/' | gawk -D -f /dev/null

答案2

交互方式,只需使用


非交互式地,如果您想编写表达式计算的脚本:

$ cat file
180/1149
(150+141)/1149
1 + 2
2 * 3 - 5

$ bc < file
.15665796344647519582
.25326370757180156657
3
1

为了交错输入和输出,我们可以使用

$ paste -d '\n' file <(bc < file)
180/1149
.15665796344647519582
(150+141)/1149
.25326370757180156657
1 + 2
3
2 * 3 - 5
1

答案3

用 perl 运行它!


...或者我们也可以使用 awk。考虑以下(二阶)awk 脚本run-in-awk

#!/usr/bin/awk -f
{ system( "awk 'BEGIN{print " $0 "}' ") }

chmod +x run-in-awk在我们实际上要求 awk 运行 awk之后

$ run-in-awk example
0.156658
0.156658
0.253264
0.253264
3
3
1
1

它还适用于标准输入键盘输入。

答案4

当我们可以将 sh 与 awk 一起使用时,为什么只使用 awk 或 perl?

#!/bin/sh
while read e_x__p_ress_ion___; do
    awk "BEGIN{print ${e_x__p_ress_ion___}}"
done

这将读取一个表达式并将其保存到一个变量中。然后调用 awk print 并传递变量。这是一个在 control-c 上退出的无限循环。

这样一个奇怪的变量名是用来保护脚本不改变其他脚本的变量的。

相关内容