【问题标题】:How to coerce AWK to evaluate string as math expression?如何强制 AWK 将字符串评估为数学表达式?
【发布时间】:2019-01-12 04:22:46
【问题描述】:

有没有办法在 awk 中将字符串计算为数学表达式?

balter@spectre3:~$ echo "sin(0.3) 0.3" | awk '{print $1,sin($2)}'
sin(0.3) 0.29552

我想知道一种将第一个输入也评估为 0.29552 的方法。

【问题讨论】:

  • 使用这个echo "sin(0.3) 0.3" | awk '{match($1,/\(.*\)/);print sin(substr($1,RSTART+1,RLENGTH-1)),sin($2)}' 怎么样 :) 我知道你想把它作为一个数学表达式传递(我现在还不知道,正在寻找文档),想一个有趣的方式来玩用这个。
  • 嗯,网上流传着 Kenny McCormack 和 Alan Linton 的 calc3 awk 脚本的扩展版本,这里有一个链接:groups.google.com/forum/#!topic/comp.lang.awk/C4SbutsY1JA 原版calc3 仅支持基本操作,但链接的人似乎可以处理罪恶等。
  • echo "sin(0.3)" | awk -f calc3.awk 产生sin(0.3) = 0.29552
  • echo "sin(0.3) 0.3" | perl -ne ' /(\S+)\s+(\S+)/ and print eval($1), " ", $2 ' 也可以..

标签: math awk evaluate


【解决方案1】:

您可以创建自己的 eval 函数,该函数再次调用 awk 来执行您希望它执行的任何命令:

$ cat tst.awk
{ print eval($1), sin($2) }

function eval(str,      cmd,line,ret) {
    cmd = "awk \047BEGIN{print " str "; exit}\047"
    if ( (cmd | getline line) > 0 ) {
        ret = line
    }
    close(cmd)
    return ret
}

$ echo 'sin(0.3) 0.3' | awk -f tst.awk
0.29552 0.29552

$ echo '4*7 0.3' | awk -f tst.awk
28 0.29552

$ echo 'tolower("FOO") 0.3' | awk -f tst.awk
foo 0.29552

【讨论】:

    【解决方案2】:

    这是一个简单的衬里!

    math(){ awk "BEGIN{printf $1}"; }
    

    使用示例:

    math 1+1  
    

    产量“2”

    math 'sqrt(25)'
    

    产量“5”

    x=100; y=5; math "sqrt($x) + $y"
    

    产生“15”

    【讨论】:

      【解决方案3】:

      awk 缺少eval(...) 函数。这意味着您不能在 awk 程序初始化后根据输入进行字符串到代码的转换。好的,也许可以做到,但必须在 awk 中编写自己的解析和评估引擎。

      我建议使用bc 来完成这项工作,比如

      [edwbuck@phoenix ~]$ echo "s(0.3)" | bc -l
      .29552020666133957510
      

      请注意,这需要将sin 缩短为s,因为这是bc 正弦运算。

      【讨论】:

      • 为什么没有一个健全的 linux 命令行数学库?我目前的解决方案是m(){ python -c "import math; print($1);}。我也可以使用 perl。我以前的老板看到了这个,告诉我我刚刚制造了世界上最昂贵的计算器。
      • @abalter 我在想bc 是为basic calculator 服务的,并且满足了“理智的命令行数学”的需求;但是,在 Linux 中做数学的方法并不缺乏。我同意s(..)c(...) 是写sincos 的奇怪方式,很遗憾他们没有选择sin(...)cos()。此外,几乎可以使用 bash 的 echo $(($expr)) 方法,只是它不支持触发。
      • @EdwinBuck 有趣的是,POSIX 将 bc 中的函数和变量名称限制为单个字母。 (虽然可以使用多字母实现)
      • @abalter wrt Why isn't there a sane command line math library for linux? - 因为这不是外壳的用途。 shell 是一个调用工具的环境,它有一种小语言来帮助对这些调用进行排序。它并非旨在/设计为功能齐全的编程语言,如果您尝试这样使用它,那么您就错过了重点。
      【解决方案4】:

      使用 gawk 4.1.2 版:

      echo "sin(0.3) 0.3" | awk '{split($1,a,/[()]/);f=a[1];print @f(a[2]),sin($2)}'
      

      tolower(FOO) 也可以。

      【讨论】:

      • 对于采用单个数字或字符串参数的函数调用的好主意(例如,您不能将它与 4*7index("abc","b")sin(0.1+0.2) 一起使用)。顺便说一句[(]|[)] = [()].
      【解决方案5】:

      你可以试试 Perl,因为它有 eval() 函数。

      $  echo "sin(0.3)" | perl -ne ' print eval '
      0.29552020666134
      $
      

      对于给定的输入,

      $ echo "sin(0.3) 0.3" | perl -ne ' /(\S+)\s+(\S+)/ and print eval($1), " ", $2 '
      0.29552020666134 0.3
      $
      

      【讨论】:

        猜你喜欢
        • 2012-09-04
        • 2012-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-17
        • 1970-01-01
        相关资源
        最近更新 更多