如何打印刚刚设置的环境变量?
NAME=sam echo "$NAME" # empty
您可以在这里使用eval
它。是这样吗
NAME=sam eval 'echo $NAME' # => sam
Answers:
这些需要作为不同的命令使用,例如:
NAME=sam; echo "$NAME"
NAME=sam && echo "$NAME"
$NAME
Shell会在运行之前更早地将其扩展为空字符串echo
,因此,在将NAME
变量传递到echo
命令环境时,扩展已经完成(至null字符串)。
要在一个命令中获得相同的结果:
NAME=sam printenv NAME
printenv
。希望一切顺利,@ heemayl
printenv
-based命令保留了OP命令的语义:将其定义NAME
为命令范围的环境变量,只有被调用的命令及其子进程可以看到,而后续的shell命令则看不到。其他命令做的事情却大不相同:它们定义NAME
为“直到当前外壳退出”仅外壳变量,所有后续的外壳命令都可以看到该变量,但没有外部实用程序。
将现有答案与重要说明结合在一起:
如前所述,问题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"'
printenv
不是POSIX实用程序,但在Linux和macOS / BSD上均可用。
这种调用方式(<var>=<name> cmd ...
)的作用是定义NAME
:
换句话说:NAME
仅对于被调用的命令存在,并且对当前外壳无效(如果NAME
之前没有命名的变量存在,则之后将没有任何NAME
变量;先前存在的变量保持不变)。
POSIX在其POSIX中定义了这种调用的规则 命令搜索和执行”一章中。
以下解决方案的工作方式非常不同(与heemayl的答案相同):
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
在命令完成后仍保留在作用域内,但这不会发生。
但是,当您bash
以POSIX兼容模式运行时,它是兼容的。
dash
并且ksh
始终合规。
确切的规则很复杂,某些方面要由实现决定。再次,请参阅命令搜索和执行。
同样,通常的免责声明适用:仅在完全控制或隐式信任的输入上使用eval
。
NAME=sam echo whatever
不会更改NAME
shell中的值。