假设您将以下命令存储在变量中:
COMMAND='echo hello'
有什么区别
$ eval "$COMMAND" hello $ bash -c "$COMMAND" hello $ $COMMAND hello
?为什么最后一个版本几乎从不使用,如果它更短并且(据我所知)完全相同的事情?
第三种形式与其他两种形式完全不同 - 但要理解为什么,我们需要在解释命令时按bash进行操作,并查看每种方法在使用时遵循哪些操作.
Bash解析阶段报价处理
拆分命令
特殊操作员解析
展开
单词分裂
通配符
执行
eval "$string"
eval "$string"
遵循从#1开始的所有上述步骤.从而:
字符串中的字面引号成为语法引号
特殊操作员如>()
被处理
像这样的扩展$foo
很荣幸
这些扩展的结果在字符上分成空格分成单独的单词
如果这些单词解析为相同且具有可用匹配,那么这些单词将扩展为globs,最后执行该命令.
sh -c "$string"
...执行与此相同eval
,但在作为单独进程启动的新shell中 ; 因此,当这个新进程退出时,对变量状态,当前目录等的更改将到期.(注意,那就是,新的外壳可以是不同的解释支持不同的语言;即sh -c "foo"
不支持相同的语法bash
,ksh
,zsh
等做的).
$string
...从第5步开始,"Word Splitting".
这是什么意思?
printf '%s\n' "two words"
因此printf
%s\n
"two
words"
,将解析为(通常/期望的行为)printf
%s\n
two words
(由shell使用引号).
;
s,&
s或类似).从而:
s='echo foo && echo bar' $s
...将发出以下输出:
foo && echo bar
...而不是以下,否则将是预期的:
foo bar
不$(foo)
,不$foo
,不<(foo)
,等等
>foo
或者2>&1
只是字符串拆分创建的另一个单词,而不是shell指令.