ash*_*gpu 266 shell echo environment-variables
如果我跑
export TEST=foo
echo $TEST
Run Code Online (Sandbox Code Playgroud)
它输出 foo。
如果我跑
TEST=foo echo $TEST
Run Code Online (Sandbox Code Playgroud)
它不是。如何在不使用导出或脚本的情况下获得此功能?
pet*_*rph 311
这是因为 shell 在实际运行命令之前扩展了命令行中的变量,而此时该变量不存在。如果你使用
TEST=foo; echo $TEST
Run Code Online (Sandbox Code Playgroud)
它会起作用。
export将使变量出现在随后执行的命令的环境中(有关其在 bash 中的工作方式,请参见help export)。如果您只需要该变量出现在一个命令的环境中,请使用您尝试过的方法,即:
TEST=foo your-application
Run Code Online (Sandbox Code Playgroud)
shell 语法将其描述为在功能上等同于:
export TEST=foo
your-application
unset TEST
Run Code Online (Sandbox Code Playgroud)
有关详细信息,请参阅规范。
有趣的是,该export命令会切换变量name的导出标志。因此,如果你这样做:
unset TEST
export TEST
TEST="foo"
Run Code Online (Sandbox Code Playgroud)
TEST即使在导出时未定义,也将被导出。但是进一步unset应该从中删除导出属性。
Sté*_*las 68
我怀疑你想让shell变量有一个有限的范围,而不是环境变量。环境变量是执行命令时传递给命令的字符串列表。
在
var=value echo whatever
Run Code Online (Sandbox Code Playgroud)
您将var=value字符串传递给 echo 接收的环境。但是,echo不会对其环境列表做任何事情¹,并且无论如何在大多数 shell 中,echo都是内置的,因此不会执行。
如果你写过
var=value sh -c 'echo "$var"'
Run Code Online (Sandbox Code Playgroud)
那将是另一回事。在这里,我们传递var=value给sh命令,并且sh碰巧使用了它的环境。Shell 将从它们的环境中接收到的每个变量转换为一个 shell 变量,因此接收到的var环境变量sh将被转换为一个$var变量,当它在该echo命令行中扩展它时,它将变成echo value. 因为环境默认是继承的,echo也会var=value在它的环境中接收(或者如果它被执行了),但同样,echo不关心环境。
现在,如果我怀疑您想要的是限制 shell 变量的范围,那么有几种可能的方法。
便携(Bourne 和 POSIX):
(var=value; echo "1: $var"); echo "2: $var"
Run Code Online (Sandbox Code Playgroud)
上面的 (...) 启动一个子 shell(在大多数 shell 中是一个新的 shell 进程),所以在那里声明的任何变量只会影响那个子 shell,所以我希望上面的代码输出“1:值”和“2:”或“2:what-var-was-set-to-before”。
对于大多数类似 Bourne 的 shell,您可以使用函数和“本地”内置函数:
f() {
local var
var=value
echo "1: $var"
}
f
echo "2: $var"
Run Code Online (Sandbox Code Playgroud)
使用 zsh,您可以使用内联函数:
(){ local var=value; echo "1: $var"; }; echo "2: $var"
Run Code Online (Sandbox Code Playgroud)
或者:
function { local var=value; echo "1: $var"; }; echo "2: $var"
Run Code Online (Sandbox Code Playgroud)
使用 bash 和 zsh(但不是 ash、pdksh 或 AT&T ksh),这个技巧也有效:
var=value eval 'echo "1: $var"'; echo "2: $var"
Run Code Online (Sandbox Code Playgroud)
一个可以在更多 shell ( dash, mksh, yash) 中运行但不能运行的变体zsh(除非在sh/ksh仿真中):
var=value command eval 'echo "1: $var"'; echo "2: $var"
Run Code Online (Sandbox Code Playgroud)
(在 POSIX shell 中command的特殊内置eval函数(此处)前使用会消除它们的特殊性(此处,它们中的变量赋值在它们返回后仍然有效))
¹ 严格来说,这并不完全正确。一些实现会关心本地化环境变量(LANG, LOCPATH, LC_*...),GNU 实现会关心POSIXLY_CORRECT环境变量(env echo --version与POSIXLY_CORRECT=1 env echo --versionGNU 系统相比)。
Oli*_*ver 20
您做对了,但是 bash 语法很容易被误解:您可能认为这echo $TEST会导致echo获取TESTenv var 然后打印它,但事实并非如此。所以给出
export TEST=123
Run Code Online (Sandbox Code Playgroud)
然后
TEST=456 echo $TEST
Run Code Online (Sandbox Code Playgroud)
涉及以下顺序:
shell解析了整个命令行并执行了所有的变量替换,所以命令行变成了
TEST=456 echo 123
Run Code Online (Sandbox Code Playgroud)它创建在命令之前设置的临时变量,因此它保存当前值TEST并用 456 覆盖它;命令行现在是
echo 123
Run Code Online (Sandbox Code Playgroud)它执行剩余的命令,在这种情况下将 123 打印到标准输出(因此剩余的 shell 命令甚至不使用 的临时值TEST)
它恢复了价值 TEST
改用 printenv,因为它不涉及变量替换:
>> export TEST=123
>> printenv TEST
123
>> TEST=456 printenv TEST
456
>> printenv TEST && TEST=456 printenv TEST && TEST=789 printenv TEST && printenv TEST
123
456
789
123
>>
Run Code Online (Sandbox Code Playgroud)
您可以使用以下方法使其正常工作:
TEST=foo && echo $TEST
Run Code Online (Sandbox Code Playgroud)