43

我正在尝试通过命令调用具有修改环境的 shell 命令env

根据说明书

env HELLO='Hello World' echo $HELLO

应该 echo Hello World,但事实并非如此。如果我做

HELLO='Hello World' bash -c 'echo $HELLO'

它按预期打印Hello World(感谢this answer for this info)。

我在这里想念什么?

干杯,尼克拉斯

4

5 回答 5

65

这是因为在您的第一种情况下,您当前的 shell$HELLO在运行命令之前扩展了变量。HELLO并且您当前的 shell 中没有设置变量。

env HELLO='Hello World' echo $HELLO

会这样做:

  • 展开任何给定的变量,在这种情况下$HELLO
  • 使用 3 个参数运行 env 和(一个空字符串'HELLO=Hello World',因为当前 shell 中没有设置变量)'echo'''HELLO
  • env命令将运行并HELLO='Hello World'在其环境中设置
  • envecho使用参数''(空字符串)运行

如您所见,当前 shell 扩展了$HELLO未设置的变量。

HELLO='Hello World' bash -c 'echo $HELLO'

会这样做:

  • HELLO='Hello World为以下命令设置变量
  • 使用 2 个参数运行 bash'-c''echo $HELLO'
  • 因为最后一个参数用单引号括起来,所以里面没有任何东西被扩展
  • 新的 bash 将依次运行命令echo $HELLO
  • $HELLO为了在新的 bash 子 shell 中运行 echo ,bash 首先扩展它可以扩展的任何东西,$HELLO在这种情况下,父 shellHello World为我们设置它。
  • 子shell运行echo 'Hello World'

如果您尝试这样做:

env HELLO='Hello World' echo '$HELLO'
  • 当前的 shell 会扩展它可以扩展的任何东西,因为它$HELLO是用单引号括起来的
  • 使用 3 个参数运行 env 'HELLO=Hello World''echo'并且'$HELLO'
  • env 命令将运行并HELLO='Hello World'在其环境中设置
  • env 将使用参数运行 echo'$HELLO'

在这种情况下,没有外壳可以扩展$HELLO,因此echo接收字符串$HELLO并打印出来。变量扩展仅由 shell 完成。

于 2012-12-21T22:45:14.223 回答
5

我想发生的事情类似于我也感到困惑的这种情况。

$HELLO简而言之,第一种情况下的变量扩展是由其环境中没有的当前 shell 完成的。但是,在第二种情况下,单引号会阻止当前 shell 进行变量扩展,因此一切都按预期工作。

请注意将单引号更改为双引号如何阻止此命令按您想要的方式工作:

HELLO='Hello World' bash -c "echo $HELLO"

现在这将失败,原因与您问题中的第一个命令相同。

于 2012-12-21T22:41:35.417 回答
2

这有效,对我有好处

$ MY_VAR='Hello' ANOTHER_VAR='World!!!' && echo "$MY_VAR $ANOTHER_VAR"
Hello World!!!
于 2016-04-18T17:23:56.047 回答
2

这是确认 shell 是否按预期工作的更简单方法。

env A=42 env
env

第一个命令设置A为 42 并运行env。第二个命令也运行env。比较两者的输出。

于 2017-03-17T14:06:32.500 回答
1

如前所述,传递给的变量的扩展echo发生在该变量设置之前。

较早的答案中尚未提到的一种替代方法是使用:

$ a=abc eval 'echo $a'
abc

$ echo $a
<blank>

请注意,您必须使用a=abc cmd语法而不是env a=abc cmd语法;显然env与内置的eval.

于 2021-03-25T11:14:16.510 回答