如何打印刚设置的环境变量?
NAME=sam echo "$NAME" # empty
你可以在这里看到使用eval
它的工作原理。这是这样的吗?
NAME=sam eval 'echo $NAME' # => sam
这些需要作为不同的命令,例如:
NAME=sam; echo "$NAME"
NAME=sam && echo "$NAME"
在运行$NAME
之前,将echo
扩展为空字符串是由shell完成的,所以当NAME
变量传递给echo
命令的环境时,扩展已经完成(为null字符串)。
要在一个命令中获得相同的结果:
NAME=sam printenv NAME
将现有答案与重要说明结合起来:
如上所述,NAME=sam echo "$NAME"
的问题是$NAME
在赋值NAME=sam
生效之前被当前shell扩展。
保留原始语义的解决方案((无效)解决方案尝试NAME=sam echo "$NAME"
):
使用eval
[1](如问题本身)或printenv
(由Aaron McDaid添加到heemayl's answer)或bash -c
(来自Ljm Dullaart's answer),按效率降序排列:
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"'
printenv
不是POSIX实用程序,但它可以在Linux和macOS / BSD上使用。
这种调用方式(<var>=<name> cmd ...
)的作用是定义NAME
:
换句话说:NAME
仅对被调用的命令存在,并且对当前shell没有影响(如果之前没有名为NAME
的变量,则之后将不存在;预先存在的NAME
变量保持不变)。
POSIX在其Command Search and Execution章节中定义了这种调用的规则。
以下解决方案的工作方式非常不同(来自heemayl's answer):
NAME=sam; echo "$NAME"
NAME=sam && echo "$NAME"
虽然它们产生相同的输出,但它们定义:
NAME
(仅)而不是环境变量
如果echo
是一个依赖于环境变量NAME
的命令,它将不会被定义(或者可能与之前的定义不同)。请注意,每个环境变量也作为shell变量公开,但反之则不正确:shell变量仅对当前shell及其子shell可见,但对子进程(如外部实用程序和(非源)脚本)不可见(除非它们用export
或declare -x
标记为环境变量)。
[1]从技术上讲,bash
在这里违反了POSIX(和zsh
一样):由于eval
是一个内置的特殊shell,前面的NAME=sam
赋值应该导致变量$NAME
在命令完成后保留在范围内,但那不是怎么了。
但是,当您在POSIX兼容模式下运行bash
时,它是兼容的。
dash
和ksh
始终是合规的。
确切的规则很复杂,有些方面需要由实现来决定;再次,请参阅Command Search and Execution。
此外,通常的免责声明适用:Use eval
only on input you fully control or implicitly trust。
语法
variable=value command
通常用于为特定进程设置环境变量。但是,您必须了解哪个进程获取哪个变量以及谁解释它。例如,使用两个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'
第一个回声的结果为5,第二个回声的结果为3。
这也适用于分号。
NAME=sam; echo $NAME