运行 带有环境变量的存储命令
Running stored command with environment variables
这适用于 sh
:
$ export command="true"
$ "$command"
如果我需要将一些变量传递给命令,但是我无法让它工作:
$ export command="env FOO=\"bar\" true"
$ "$command"
sh: 2: env FOO="bar" true: not found
缺少什么?
由于您将 $command
放在引号中,这会阻止 shell 对其内容执行字段拆分,因此它被视为一个单词。因此,它尝试 运行 的 of 命令的名称是 $command
的全部内容,包括它的 spaces 和双引号字符。
您可以省略引号,这几乎可以满足您的要求:
export command="env FOO=\"bar\" true"
$command
除此之外,这会将 FOO
设置为 "bar"
(带双引号),而不是您可能期望的 bar
(不带引号)。如果您尝试将 FOO
设置为其中包含 space 的内容,它也将不起作用:
$ 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
上执行替换、拆分、扩展和引号删除,就好像它是输入到 [=59 中的命令一样=].
但是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
命令的环境。
这适用于 sh
:
$ export command="true"
$ "$command"
如果我需要将一些变量传递给命令,但是我无法让它工作:
$ export command="env FOO=\"bar\" true"
$ "$command"
sh: 2: env FOO="bar" true: not found
缺少什么?
由于您将 $command
放在引号中,这会阻止 shell 对其内容执行字段拆分,因此它被视为一个单词。因此,它尝试 运行 的 of 命令的名称是 $command
的全部内容,包括它的 spaces 和双引号字符。
您可以省略引号,这几乎可以满足您的要求:
export command="env FOO=\"bar\" true"
$command
除此之外,这会将 FOO
设置为 "bar"
(带双引号),而不是您可能期望的 bar
(不带引号)。如果您尝试将 FOO
设置为其中包含 space 的内容,它也将不起作用:
$ 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
上执行替换、拆分、扩展和引号删除,就好像它是输入到 [=59 中的命令一样=].
但是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
命令的环境。