2015-07-04 87 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