命令行上的Bash表达式评估顺序

时间:2012-02-03 00:49:01

标签: bash shell eval arguments

背景

我正在努力快速调用SGE的作业提交程序qSub中的bash命令行表达式。在这样做时,我试图提交一个表达式(作为参数)在另一个脚本中运行,如下所示:

  

./ runArguments.sh grep foo bar.txt> output.txt的

runArguments.sh 如下所示:

#!/bin/bash  
${1} ${2} ${3} etc....to 12

我的想法是,我希望在脚本中评估“grep foo bar.txt> output.txt”...不在命令行上。在上面的示例中,“grep foo bar.txt”将在runArguments.sh执行期间进行评估,但是将在命令行上评估输出重定向。我最终找到了一个使用“eval”的工作解决方案,如下所示,但我不明白为什么它可以工作。

问题(S)

1)为什么

./runArguments.sh eval "grep foo bar.txt > output.txt"

允许将eval和表达式作为参数,但

./runArguments.sh $(grep foo bar.txt > output.txt)

在调用脚本之前评估命令行? (取而代之的是$(grep ...)的输出作为参数)

2)有更好的方法吗?

提前致谢!

1 个答案:

答案 0 :(得分:3)

你的第一个问题有点难以回答,因为你已经自己回答了。如您所见,命令替换($(...)`...`表示法)替换命令的输出,然后处理结果。例如,这个:

cat $(echo tmp.sh)

转换为:

cat tmp.sh

所以在你的情况下,这个:

./runArguments.sh $(grep foo bar.txt > output.txt)

运行grep foo bar.txt > output.txt,抓取它的输出 - 这将不算什么,因为你已将任何输出重定向到output.txt - 并替换它,产生:

./runArguments.sh

(所以你的脚本没有参数运行)。

相比之下,这个:

./runArguments.sh eval "grep foo bar.txt > output.txt"

不执行任何命令替换,因此您的脚本使用两个参数运行:evalgrep foo bar.txt > output.txt。脚本中的此命令:

${1} ${2} ${3} ${4} ${5} ${6} ${7} ${8} ${9} ${10} ${11} ${12}
因此,

等同于:

eval grep foo bar.txt '>' output.txt

使用五个参数调用eval内置函数:grepfoobar.txt>output.txteval内置将其参数组装成一个命令,并运行它们,甚至将>output.txt参数转换为输出重定向,因此上述内容等同于:

grep foo bar.txt > output.txt

。 。 。而你已经知道那是做什么的。 : - )


关于你的第二个问题 - 不,没有更好的方法来做到这一点。您需要将>作为参数传递,这意味着您需要使用eval ...bash -c "..."等来将其“翻译”回意义输出重定向。如果你是O.K.修改脚本,然后您可能想要更改此行:

${1} ${2} ${3} ${4} ${5} ${6} ${7} ${8} ${9} ${10} ${11} ${12}

到此:

eval ${1} ${2} ${3} ${4} ${5} ${6} ${7} ${8} ${9} ${10} ${11} ${12}

这样您就不需要在参数中处理这个问题了。或者,实际上,您可以将其更改为:

eval ${@}

将允许您传递超过12个参数;或者,更好的是,这个:

eval "${@}"

这会让你稍微更多地控制分词和文件播放等等。