AWK:为什么$(cat) 适用于 stdin,而$* 不适用?

AWK:为什么$(cat) 适用于 stdin,而$* 不适用?
echo '((3+(2^3)) * 34^2 / 9)-75.89' | awk "BEGIN{ print $(cat) }"

上述语法对于计算结果“1337”来说运行良好。

echo '((3+(2^3)) * 34^2 / 9)-75.89' | awk "BEGIN{ print $* }"

但上述语法不起作用,尽管没有错误。

请提供建议。

答案1

$(command)语法将返回 的输出command。在这里,您使用非常简单的程序,其唯一任务是将所有内容从标准输入 (stdin) 复制到标准输出 (stdout)。由于您在双引号内cat运行脚本,因此shell 会扩展awk$(cat)脚本awk运行后,它会将echo输出读入其标准输入,并及时将其复制到标准输出。然后将其传递给脚本awk。您可以通过以下方式查看此操作set -x

$ set -x
$ echo '((3+(2^3)) * 34^2 / 9)-75.89' | awk "BEGIN{ print $(cat) }"
+ echo '((3+(2^3)) * 34^2 / 9)-75.89'
++ cat
+ awk 'BEGIN{ print ((3+(2^3)) * 34^2 / 9)-75.89 }'
1337

因此,awk实际运行BEGIN{ print ((3+(2^3)) * 34^2 / 9)-75.89 }'返回 1337。

现在,$*是一个特殊的 shell 变量,它扩展到给予 shell 脚本的所有位置参数(参见man bash):

   *      Expands to the positional parameters, starting from one.  When the expan‐
          sion  is not within double quotes, each positional parameter expands to a
          separate word.  In contexts where it is performed, those words  are  sub‐
          ject  to  further word splitting and pathname expansion.  When the expan‐
          sion occurs within double quotes, it expands to a single  word  with  the
          value  of each parameter separated by the first character of the IFS spe‐
          cial variable.  That is, "$*" is equivalent to "$1c$2c...",  where  c  is
          the  first  character of the value of the IFS variable.  If IFS is unset,
          the parameters are separated by spaces.  If IFS is null,  the  parameters
          are joined without intervening separators.

但此处此变量为空。因此,awk脚本变为:

$ echo '((3+(2^3)) * 34^2 / 9)-75.89' | awk "BEGIN{ print $* }"
+ awk 'BEGIN{ print  }'
+ echo '((3+(2^3)) * 34^2 / 9)-75.89'

扩展$*为一个空字符串,并被awk告知打印一个空字符串,这就是为什么没有输出。


您可能只想使用bc

$ echo '((3+(2^3)) * 34^2 / 9)-75.89' | bc
1336.11

相关内容