eval/bash -c 与仅评估变量相比有何意义? [英] What's the point of eval/bash -c as opposed to just evaluating a variable?
问题描述
假设您将以下命令存储在变量中:
Suppose you have the following command stored in a variable:
COMMAND='echo hello'
有什么区别
$ eval "$COMMAND"
hello
$ bash -c "$COMMAND"
hello
$ $COMMAND
hello
?如果最后一个版本更短并且(据我所知)做了完全相同的事情,为什么几乎从未使用过它?
? Why is the last version almost never used if it is shorter and (as far as I can see) does exactly the same thing?
推荐答案
第三种形式与其他两种形式完全不同——但要理解为什么,我们需要深入了解 bash 在解释命令时的操作顺序,并查看在使用每种方法时遵循了哪些方法.
The third form is not at all like the other two -- but to understand why, we need to go into the order of operations when bash in interpreting a command, and look at which of those are followed when each method is in use.
- 报价处理
- 拆分成命令
- 特殊运算符解析
- 扩展
- 分词
- 球状
- 执行
<小时>
使用 eval "$string"
eval "$string"
从 #1 开始遵循上述所有步骤.因此:
Using eval "$string"
eval "$string"
follows all the above steps starting from #1. Thus:
- 字符串中的文字引号变成句法引号
- 处理
>()
等特殊操作符 - 像
$foo
这样的扩展很受尊重 - 这些扩展的结果在字符上被拆分为空格并分成单独的单词
- 如果这些词解析为相同并且有可用的匹配项,则这些词会扩展为 globs,最后执行命令.
- Literal quotes within the string become syntactic quotes
- Special operators such as
>()
are processed - Expansions such as
$foo
are honored - Results of those expansions are split on characters into whitespace into separate words
- Those words are expanded as globs if they parse as same and have available matches, and finally the command is executed.
...执行与 eval
相同的操作,但在作为单独进程启动的新 shell 中;因此,当这个新进程退出时,对变量状态、当前目录等的更改将过期.(还要注意,新的 shell 可能是支持不同语言的不同解释器;即 sh -c "foo"
将不支持与 bash
相同的语法,ksh
、zsh
等等.
...performs the same as eval
does, but in a new shell launched as a separate process; thus, changes to variable state, current directory, etc. will expire when this new process exits. (Note, too, that that new shell may be a different interpreter supporting a different language; ie. sh -c "foo"
will not support the same syntax that bash
, ksh
, zsh
, etc. do).
...从第 5 步分词"开始.
...starts at step 5, "Word Splitting".
这是什么意思?
printf '%s
' "two words"
因此将解析为 printf
%s
"two
words"
,与 printf
%s
两个字
的通常/预期行为相反(shell 使用引号).
printf '%s
' "two words"
will thus parse as printf
%s
"two
words"
, as opposed to the usual/expected behavior of printf
%s
two words
(with the quotes being consumed by the shell).
因此:
s='echo foo && echo bar'
$s
...将发出以下输出:
...will emit the following output:
foo && echo bar
...而不是以下内容,否则会出现这种情况:
...instead of the following, which would otherwise be expected:
foo
bar
不支持特殊运算符和扩展.
没有$(foo)
,没有$foo
,没有<(foo)
等
>foo
或 2>&1
只是由字符串拆分创建的另一个词,而不是 shell 指令.
>foo
or 2>&1
is just another word created by string-splitting, rather than a shell directive.
这篇关于eval/bash -c 与仅评估变量相比有何意义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!