Bash 为什么可以';我是否指定一个环境变量并在同一命令行中回显它?
考虑一下这个片段:Bash 为什么可以';我是否指定一个环境变量并在同一命令行中回显它?,bash,environment-variables,echo,Bash,Environment Variables,Echo,考虑一下这个片段: $ SOMEVAR=AAA $ echo zzz $SOMEVAR zzz zzz AAA zzz 在这里,我在第一行将$SOMEVAR设置为AAA,当我在第二行回显它时,我得到了预期的AAA内容 但是,如果我尝试在与echo相同的命令行上指定变量: $ SOMEVAR=BBB echo zzz $SOMEVAR zzz zzz AAA zzz 。。。我没有得到预期的BBB——我得到了旧值(AAA) 事情就是这样吗?如果是这样,那么您可以指定变量,如LD\u PRELOA
$ SOMEVAR=AAA
$ echo zzz $SOMEVAR zzz
zzz AAA zzz
在这里,我在第一行将$SOMEVAR
设置为AAA
,当我在第二行回显它时,我得到了预期的AAA
内容
但是,如果我尝试在与echo
相同的命令行上指定变量:
$ SOMEVAR=BBB echo zzz $SOMEVAR zzz
zzz AAA zzz
。。。我没有得到预期的BBB
——我得到了旧值(AAA
)
事情就是这样吗?如果是这样,那么您可以指定变量,如
LD\u PRELOAD=/。。。程序参数…
是否正常工作?我遗漏了什么?您看到的是预期的行为。问题在于,父shell在使用修改后的环境调用命令之前,会在命令行上计算$SOMEVAR
。您需要将对$SOMEVAR
的评估推迟到环境设置之后
您的直接选择包括:
SOMEVAR=BBB eval echo zzz'$SOMEVAR'zzz
SOMEVAR=BBB sh-c'echo zzz$SOMEVAR zzz'
$SOMEVAR
;只有在环境中设置后才会对其进行计算(暂时,在单个命令的持续时间内)
另一种选择是使用子外壳符号(如his中的建议):
该变量仅在子shell中设置
SOMEVAR=BBB; echo zzz $SOMEVAR zzz
使用;将同一行上的语句分开。原因是这为一行设置了一个环境变量。但是,
echo
不进行扩展,bash
进行扩展。因此,即使在echo命令的上下文中,SOME_VAR
是BBB
,您的变量实际上在执行命令之前已展开
要查看效果,可以执行以下操作:
$ SOME_VAR=BBB bash -c 'echo $SOME_VAR'
BBB
在这里,直到子进程执行,变量才会展开,因此您可以看到更新的值。如果您在父shell中再次检查某个\u变量
,它仍然是AAA
,正如预期的那样。问题再次出现
坦率地说,手册在这一点上令人困惑。报告说:
任何简单命令或函数的环境[请注意,这不包括内置命令]都可以通过在其前面加上参数赋值来临时增强,如Shell参数中所述。这些赋值语句只影响该命令所看到的环境
如果你真的分析了这个句子,它所说的是命令/函数的环境被修改了,而不是父进程的环境。因此,这将起作用:
$ TESTVAR=bbb env | fgrep TESTVAR
TESTVAR=bbb
因为env命令的环境在执行之前已被修改。但是,这将不起作用:
$ set -x; TESTVAR=bbb echo aaa $TESTVAR ccc
+ TESTVAR=bbb
+ echo aaa ccc
aaa ccc
因为当shell执行参数扩展时
解释器步骤
问题的另一部分是Bash对于它的解释器:
要实现您的目标,请使用
( SOMEVAR=BBB; echo zzz $SOMEVAR zzz )
原因:
- 必须用分号或新行将赋值与下一个命令分开,否则在下一个命令(echo)进行参数扩展之前不会执行赋值
- 您需要在子shell环境中进行分配,以确保它不会持续超过当前行
此解决方案比其他一些建议的解决方案更短、更整洁、更高效,尤其是它不会创建新流程。这里有一个替代方案:
SOMEVAR=BBB && echo zzz $SOMEVAR zzz
将把SOMEVAR=BBB
添加到环境变量中,然后执行echo zzz$SOMEVAR zzz
。$SOMEVAR
是指shell变量SOMEVAR
,您事先已将其设置为AAA
添加分号SOMEVAR=BBB;echo zzz$SOMEVAR zzz
将shell变量设置为BBB
,然后在分号后执行命令,即echo zzz$SOMEVAR zzz
并生成zzz BBB zzz
请尝试以下命令:
SOMEVAR=BBB env | less
再看看环境。让我们来了解一下为什么它不仅在bash中,而且在任何兼容的shell中都会这样:
2.10.2,Shell语法规则 根据规则7(b),包括在简单命令之前进行赋值的情况: <
SOMEVAR=BBB echo zzz $SOMEVAR zzz
SOMEVAR=BBB env | less
SOMEVAR=BBB sh -c 'echo "$SOMEVAR"'
{ SOMEVAR=BBB; echo "$SOMEVAR"; } | somecommand ...