export TEST=foo
echo $TEST
它输出foo。
如果我运行
TEST=foo echo $TEST
/>没有。如何在不使用导出或脚本的情况下获得此功能?
#1 楼
这是因为shell在实际运行命令之前在命令行中扩展了该变量,而那时该变量不存在。如果使用TEST=foo; echo $TEST
它将起作用。
export
将使变量出现在随后执行的命令的环境中(有关此在bash中工作,请参阅help export
)。如果只需要变量出现在一个命令的环境中,请使用您尝试过的方法,即:TEST=foo your-application
评论
/ usr / bin / env呢?那也不行,你知道为什么吗?
– Benubird
2014年7月9日在16:43
相同的原因-shell在执行命令行之前扩展$ TEST。运行echo后(还要注意echo通常会转换为shell内置命令而不是/ bin / echo),它会在其环境中看到设置的变量。但是,echo $ TEST不会告诉echo从其环境中输出变量TEST的内容。它告诉外壳程序运行echo,并且参数是TEST变量中当前存在的参数-这是两个非常不同的东西。
–彼得
2014年7月9日17:41
@peterph如果shell在实际运行命令之前在命令行中扩展了变量,那么为什么不在var = value sh -c'echo“ $ var”'中将其扩展呢?
–架子
18年3月12日在21:56
正如我在这里向您解释的:这是因为变量在双引号内(例如,“…$ var…”)而不是在单引号内(例如,“…$ var…”)扩展。由于echo“ $ var”在单引号内,因此整个字符串将传递到新(sh-c)外壳,而无需由外部交互式外壳解释。 …(续)
– G-Man说“恢复莫妮卡”
18年3月14日在20:21
(续)…正如igal昨天所说,有两轮解析-尽管我相信igal会误读您的问题。除了由父shell进行的解析外,没有两轮解析。进行两轮解析-一轮由外部交互(父)外壳完成,而一轮由新的(sh-c)子外壳完成。
– G-Man说“恢复莫妮卡”
18年3月14日在20:21
#2 楼
我怀疑您想让shell变量具有有限的作用域,而不是环境变量。环境变量是执行时传递给命令的字符串的列表。在
var=value echo whatever
您要将
var=value
字符串传递给回声接收的环境。但是,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"
上面的(...)启动了一个子外壳(大多数外壳中都有一个新的外壳过程),因此在那里声明的任何变量都只会影响该子外壳,因此我希望上面的代码输出“ 1:值”和“ 2:”或“ 2:what-var-was-set-before”。
对于大多数类似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"
一个可以在更多shell中使用的变体(
dash
,mksh
和yash
),但不能在zsh
中使用(除非在sh
/ ksh
仿真中有效):var=value command eval 'echo "1: $var"'; echo "2: $var"
(在前面使用
command
POSIX shell中特殊的内置函数(此处为eval
)的使用消除了它们的特殊性(此处返回的变量分配在返回后仍然有效)。¹完全正确。几种实现方式将关心本地化环境变量(
LANG
,LOCPATH
,LC_*
...),GNU实现则关心POSIXLY_CORRECT
环境变量(将env echo --version
与POSIXLY_CORRECT=1 env echo --version
在GNU系统上进行比较)。评论
对我而言,这是正确的解决方案。我不希望变量'var'像接受的答案那样污染环境。
– kronenpj
17年9月13日在15:12
#3 楼
您做得正确,但是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
>>
评论
+1我发现printenv有助于测试/概念验证(行为类似于脚本,而不是echo)
–达里恩
19年1月7日在8:28
#4 楼
您可以使用以下方法来工作:TEST=foo && echo $TEST
评论
在这种情况下,TEST = foo作为单独的语句运行-它不仅在echo上下文中设置。
– codeforester
17年1月3日,19:54
评论
小心一点,这个故事比最初出现的更多。我邀请您检查我的答案。