命令行上的 Bash 表达式评估顺序 [英] Bash Expression Evaluation Order on Command Line

查看:18
本文介绍了命令行上的 Bash 表达式评估顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

背景:

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

I'm working on quickly calling bash command line expressions inside of SGE's job submission program qSub in parallel. While doing so, I was attempting to submit an expression (as an argument) to be ran inside of another script like so:

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

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

runArguments.sh 看起来像这样:

runArguments.sh looks like this:

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

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

The idea is that I want "grep foo bar.txt > output.txt" to be evaluated in the script...NOT ON THE COMMAND LINE. In the example above, "grep foo bar.txt" will evaluate during runArguments.sh execution, but the output redirection would be evaluated on the command line. I eventually found a working solution using "eval" that is shown below, but I do not understand why it works.

问题

1) 为什么

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

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

allow the eval and the expression to be taken as arguments, but

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

在调用脚本之前在命令行上进行评估?($(grep...) 的输出被当作参数)

evaluates on the command line before the script is called? (the output of $(grep...) is taken as the arguments instead)

2) 有没有更好的方法来做到这一点?

2) Is there a better way of doing this?

提前致谢!

推荐答案

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

Your first question is a bit hard to answer, because you've already answered it yourself. As you've seen, command substitution (the $(...) or `...` notation) substitutes the output of the command, and then processes the result. For example, this:

cat $(echo tmp.sh)

被转换成这样:

cat tmp.sh

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

So in your case, this:

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

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

runs grep foo bar.txt > output.txt, grabs its output — which will be nothing, since you've redirected any output to output.txt — and substitutes it, yielding:

./runArguments.sh

(因此您的脚本在没有参数的情况下运行).

(so your script is run with no arguments).

相比之下,这个:

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

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

does not perform any command substitution, so your script is run with two arguments: eval, and grep foo bar.txt > output.txt. This command inside your script:

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

因此等价于:

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

它使用五个参数调用内置的 eval:grepfoobar.txt>output.txt.eval 内置函数将它的参数组装成一个命令,并运行它们,甚至将 >output.txt 参数翻译成一个命令输出重定向,所以上面等价于这个:

which invokes the eval built-in with five arguments: grep, foo, bar.txt, >, and output.txt. The eval built-in assembles its arguments into a command, and runs them, and even translates the > and output.txt arguments into an output-redirection, so the above is equivalent to this:

grep foo bar.txt > output.txt

...你已经知道它的作用了.:-)

. . . and you already know what that does. :-)

至于你的第二个问题—不,没有更好的方法来做到这一点.您需要将 > 作为参数传入,这意味着您需要使用 eval ...bash -c "..." 等,以便将其翻译"回表示输出重定向.如果你没事修改脚本后,您可能需要更改此行:

As for your second question — no, there's not really a better way to do this. You need to pass the > in as an argument, and that means that you need to use eval ... or bash -c "..." or the like in order to "translate" it back into meaning output-redirection. If you're O.K. with modifying the script, then you might want to change this line:

${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}

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

so that you don't need to handle this in the parameters. Or, actually, you might as well change it to this:

eval ${@}

这会让你传入十二个以上的参数;或者,更好的是:

which will let you pass in more than twelve parameters; or, better yet, this:

eval "${@}"

这将使您稍微更好地控制分词和文件通配等.

which will give you slightly more control over word-splitting and fileglobbing and whatnot.

这篇关于命令行上的 Bash 表达式评估顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆