使用环境变量运行存储的命令

时间:2015-03-06 16:54:41

标签: sh

这适用于sh

$ export command="true"
$ "$command"

但是,如果我需要将一些变量传递给命令,我无法使其工作:

$ export command="env FOO=\"bar\" true"
$ "$command"
sh: 2: env FOO="bar" true: not found

缺少什么?

1 个答案:

答案 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命令的环境中。