这适用于sh
:
$ export command="true"
$ "$command"
但是,如果我需要将一些变量传递给命令,我无法使其工作:
$ export command="env FOO=\"bar\" true"
$ "$command"
sh: 2: env FOO="bar" true: not found
缺少什么?
答案 0 :(得分:1)
由于您已将$command
放在引号中,这会阻止shell对其内容执行字段拆分,因此将其视为一个单词。因此,它尝试运行的命令的名称是$command
的完整内容,包括它的空格和双引号字符。
你可以省略引号,这几乎可以达到你想要的效果:
export command="env FOO=\"bar\" true"
$command
除非这样,否则会将FOO
设置为"bar"
(使用双引号)而不是bar
(不带引号)。如果您尝试将FOO
设置为包含空格的内容,它也将无效:
$ command="env FOO=\"bar foo\" true"
$ $command
env: foo": No such file or directory
这里的问题是变量command
中的双引号字符被替换后被视为任何其他字符。它们不会被移除,也不会阻止场分裂。
您可以使用eval
命令:
command="env FOO=\"bar foo\" true"
eval "$command"
这会导致shell再次完全重新评估eval
之后的所有内容并作为命令执行。换句话说,在eval "$command"
上进行替换,拆分,扩展和引用删除后,它会在env FOO="bar foo" true
上执行替换,拆分和扩展以及引用删除,就好像它是输入shell的命令一样。 / p>
然而,eval
命令非常危险。你必须相信你传递给它的一切。如果你传递来自不受信任的用户的东西,那么用户可以创建一个字符串,让他运行他想要的任何命令。
作为eval
的替代方案,您可以使用alias
或函数。 alias
命令和eval
一样危险,但是如果你只是从命令提示符中使用$command
而从不使用脚本,那么使用别名是最简单的最简单的解决方案:
$ alias mycommand="env FOO=\"bar\" true"
$ mycommand
如果您在shell脚本中使用它,或者在命令行和shell脚本中使用它,我会使用一个函数:
myfunc() {
env FOO="bar" true
}
myfunc
另外,在使用其中一个Bourne shell时,实际上不需要使用env
为命令设置环境变量,只需设置变量:
FOO="bar" true
当像这样使用时,变量赋值与env
命令一样,它不会在shell的环境中更改FOO
的值,仅在true
命令的环境中。