如何打印/回显环境变量?

Tho*_*ggi 50 bash eval

如何打印刚设置的环境变量?

NAME=sam echo "$NAME" # empty
Run Code Online (Sandbox Code Playgroud)

你可以看到这里使用eval它的工作原理.这是这样的吗?

NAME=sam eval 'echo $NAME' # => sam
Run Code Online (Sandbox Code Playgroud)

hee*_*ayl 52

这些需要作为不同的命令,例如:

NAME=sam; echo "$NAME"
NAME=sam && echo "$NAME"
Run Code Online (Sandbox Code Playgroud)

$NAME在运行之前,由shell先完成对空字符串的扩展echo,因此在将NAME变量传递给echo命令的环境时,扩展已经完成(为空字符串).

要在一个命令中获得相同的结果:

NAME=sam printenv NAME
Run Code Online (Sandbox Code Playgroud)

  • 请注意,只有基于 `printenv` 的命令保留了 OP 命令的语义:将 `NAME` 定义为 _command-scoped 环境变量_,只有被调用的命令及其子进程可以看到,但没有后续的 shell 命令。其他命令做一些非常不同的事情:他们将`NAME`定义为_until-the-current-shell-exits shell-only variable_,所有后续_shell_命令都可以看到,但_没有外部实用程序_。 (2认同)

mkl*_*nt0 8

将现有答案与重要说明结合在一起:

如前所述,问题NAME=sam echo "$NAME"在于赋值生效之前$NAME,当前的shell会对其进行扩展。NAME=sam

保留原始语义的解决方案(无效尝试的尝试NAME=sam echo "$NAME"):

使用eval[1] (如问题本身),或printenv(按Aaron McDaid在heemayl的答案中所添加)或bash -c((根据Ljm Dullaart的答案)按效率降序排列:

NAME=sam eval 'echo "$NAME"'  # use `eval` only if you fully control the command string
NAME=sam printenv NAME
NAME=sam bash -c 'echo "$NAME"'
Run Code Online (Sandbox Code Playgroud)

printenv 不是POSIX实用程序,但在Linux和macOS / BSD上均可用。

这种调用方式(<var>=<name> cmd ...)的作用是定义NAME

  • 作为环境变量
  • 只对被调用的命令定义

换句话说:NAME仅对于被调用的命令存在,并且对当前外壳无效(如果NAME之前没有命名的变量存在,则之后将没有任何NAME变量;预先存在的变量保持不变)。

POSIX在“ 命令搜索和执行”一章中定义了这种调用的规则。


以下解决方案的工作方式非常不同(与heemayl的答案相同):

NAME=sam; echo "$NAME"
NAME=sam && echo "$NAME"
Run Code Online (Sandbox Code Playgroud)

当它们产生相同的输出时,它们定义:

  • 一个变量NAME(只),而不是一个环境变量
    • 如果echo是依赖于环境变量的命令NAME,则不会进行定义(或可能与之前的定义有所不同)。
  • 住在该命令后。

请注意,每个环境变量也都作为shell变量公开,但反之则不成立:shell变量仅对当前shell及其子shell可见,而对子进程可见,例如外部实用程序和(非源代码)脚本(除非使用export或将它们标记为环境变量declare -x)。


[1]从技术上讲,bash这里违反了POSIX(按原样zsh):由于eval是内置的特殊 Shell,因此前面的NAME=sam赋值应该使变量$NAME在命令完成后仍保留在作用域中,但这不会发生。
但是,当您bash以POSIX兼容模式运行时,它兼容的。
dash并且ksh始终合规。
确切的规则很复杂,并且某些方面要由实现决定。再次,请参阅命令搜索和执行
同样,通常的免责声明适用:仅在完全控制或隐式信任的输入上使用eval


Tho*_*ggi 7

这也适用于分号。

NAME=sam; echo $NAME


Ljm*_*art 6

语法

variable=value command
Run Code Online (Sandbox Code Playgroud)

通常用于为特定进程设置环境变量。但是,您必须了解哪个进程获取哪个变量以及谁解释它。例如,使用两个 shell:

a=5
# variable expansion by the current shell:
a=3 bash -c "echo $a"
# variable expansion by the second shell:
a=3 bash -c 'echo $a'
Run Code Online (Sandbox Code Playgroud)

第一个回波的结果将为 5,第二个回波的结果将为 3。