2015-07-04 46 views
2
$ a=one; echo $a 
one 
$ a=two echo $a 
one 
$ echo $a 
one 

a的值将初始化为'two',但它为什么显示'one'?Bash如何解释这些陈述?

+0

工作正常,我。 '''bash-3.2 $ a = 1 bash-3。2 $ echo $ a one bash-3.2 $ a = two bash-3.2 $ echo $ a two''' – osman

+0

我同意你的意见,但是,我的脚本在fedora 21上运行有什么问题? –

+0

我可以验证行为,但我无法解释它。有趣的问题! – arkascha

回答

3

env变量的同一行初始化仅适用于子shell。

这将更加明显,从这些例子:

unset a 

a=two echo "<$a>" 
<> 

a=two bash -c 'echo "<$a>"' 
<two> 

echo "<$a>" 
<> 

在它打印<two>因为我们用产卵一个bash -c子shell第二个片段。

+0

也看看:http://stackoverflow.com/a/30984437/548225 – anubhava

+0

对不起,我没有看到你的例子发布我的。 –

+0

哦,没有问题,你也添加了一个很好的解释。 – anubhava

1

这是由于shell处理替换和变量的顺序。根据POSIX rules for a shell

当需要一个给定的简单的命令要被执行(即,当 任何条件结构例如AND-OR列表或case语句 没有绕过简单的命令),则

  1. 词被识别为可变分配或根据壳牌语法规则重定向被保存用于处理:以下的扩展, 赋值和重定向均应从 开始命令文本到端部的情况下进行 步骤3和步骤4.

  2. 不应变量赋值或重定向的单词应扩展。如果任何字段在扩展后仍然存在,则第一个 字段应被视为命令名称,其余字段为该命令的参数 。

  3. 重定向应按照重定向中的描述执行。

  4. 在分配值之前,每个变量分配都应扩展用于波形扩展,参数扩展,命令替换,算术扩展和删除报价。

这意味着已经发生参数扩展之后执行的变量赋值,例如$a已在处理该命令的a=变量分配之前展开。 a的新值将被传递到命令的执行环境中,但在这种情况下echo不会有任何用处。

如果您使用一个尚不存在的变量,您可能会看到更好的情况。

$ unset a 
$ a=two echo \($a\) 
() 
$ a=one 
$ a=two echo \($a\) 
(one) 

这里有一个例子,你可以看到变量赋值传递给所执行的命令的执行环境:

$ a=one 
$ a=two python -c 'import os;print(os.environ["a"])' 
two