Answers:
这是因为Shell在实际运行命令之前在命令行中扩展了该变量,而那时该变量不存在。如果您使用
TEST=foo; echo $TEST
它会工作。
export
将使变量出现在随后执行的命令的环境中(有关bash的工作原理,请参见help export
)。如果只需要变量出现在一个命令的环境中,请使用您尝试过的方法,即:
TEST=foo your-application
$TEST
执行命令行之前将展开。一旦echo
正在运行(也注意到,echo
通常会转化为内置的命令,而不是外壳/bin/echo
),它认为在其环境变量设置。但是,echo $TEST
不要告诉要从其环境echo
输出变量的内容TEST
。它告诉外壳程序以echo
参数作为当前运行的参数运行TEST
-这是两个非常不同的东西。
var=value sh -c 'echo "$var"'
?
我怀疑您想让shell变量具有有限的作用域,而不是环境变量。环境变量是执行时传递给命令的字符串的列表。
在
var=value echo whatever
您正在将var=value
字符串传递给echo接收的环境。但是,echo
它对环境列表不做任何事情,并且在大多数shell中无论如何echo
都是内置的,因此不执行。
如果你写过
var=value sh -c 'echo "$var"'
那将是另一回事。在这里,我们传递var=value
给该sh
命令,并且sh
确实使用了它的环境。Shell将它们从环境中接收到的每个变量都转换为Shell变量,因此接收到的var
环境变量sh
将被转换为$var
变量,并且在该echo
命令行中对其进行扩展时,它将变为echo value
。因为默认情况下环境是继承的,所以echo
也会var=value
在其环境中接收(或将在环境中执行),但是同样,echo
它并不关心环境。
现在,如果我怀疑要限制外壳程序变量的范围,则有几种可能的方法。
可移植(Bourne和POSIX):
(var=value; echo "1: $var"); echo "2: $var"
上面的(...)启动了一个子shell(大多数shell中都是一个新的shell进程),因此在那里声明的任何变量都只会影响该子shell,因此我希望上面的代码输出“ 1:value”和“ 2:”或“ 2:之前设置的任何变量”。
对于大多数类似于Bourne的shell,您可以使用函数和内置的“ local”:
f() {
local var
var=value
echo "1: $var"
}
f
echo "2: $var"
使用zsh,可以使用内联函数:
(){ local var=value; echo "1: $var"; }; echo "2: $var"
要么:
function { local var=value; echo "1: $var"; }; echo "2: $var"
对于bash和zsh(但不适用于ash,pdksh或AT&T ksh),此技巧也适用:
var=value eval 'echo "1: $var"'; echo "2: $var"
一个变种,在几个弹作品(dash
,mksh
,yash
),但不zsh
(除非sh
/ ksh
模拟):
var=value command eval 'echo "1: $var"'; echo "2: $var"
(在POSIX shell中command
的特殊内置eval
函数(here )前面使用会删除它们的特殊性(此处返回的变量分配在返回后仍然有效))
您做得正确,但是bash语法很容易被误解:您可能认为echo $TEST
导致echo
获取TEST
env var的原因然后将其打印出来,但事实并非如此。因此给定
export TEST=123
然后
TEST=456 echo $TEST
涉及以下顺序:
Shell会解析整个命令行并执行所有变量替换,因此命令行变为
TEST=456 echo 123
它在命令之前创建了temp vars,因此保存了的当前值TEST
并用456覆盖了它;命令行现在
echo 123
它执行剩余的命令,在这种情况下,将123打印到stdout(因此,剩下的shell命令甚至没有使用temp的值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
>>
printenv
对测试/概念验证很有帮助(行为与脚本相反,而不是echo
)