2014-03-26 64 views
2

我正在學習shell腳本,我有這種情況。當我每次運行一個命令時,爲什麼不改變位置變量

我們說位置變量是環境變量,但是爲什麼每次執行命令時它們都不會改變。

看看這個

set v1set v2set v3set v4set 
old=$# 

#Just a random command 
ls -l 

new=$# 

echo $old $new 

它輸出4 4。如果環境變量是全局的,爲什麼它不是4 1,因爲我運行了ls -l,它應該更新位置變量?

+0

你是什麼意思的「位置變量是環境變量」 ? – justhalf

+0

當你像'ls -l'那樣運行一個命令時,無論在該命令執行期間發生了什麼(即使它涉及調用一個子shell,在本例中它不會),都不會影響當前shell中的環境。 –

+1

@Nate,請不要將人指向ABS; irc.freenode.org#bash有足夠的麻煩幫助人們忘掉自己從中汲取的壞習慣。 http://mywiki.wooledge.org/BashGuide在避免示範代碼中的不良做法方面更加謹慎得多。 –

回答

3

Interesant的問題 - 你有好點。

爲了理解它,您需要了解當您運行任何命令時會發生什麼,如ls -l。它有什麼用「的變量都將恢復或類似的」 ...

當你要運行任何命令,

  1. bash身變爲兩個相同的副本
  2. 的一個副本(稱爲小孩)將用自己想要的命令取代自己(例如,與ls -l
  3. 在這個時刻,孩子進程將獲得位置變量$#
  4. remerber的正確計數 - 這種情況對孩子的過程中,第二()進程知道這個
  5. NOTHING
  6. 父母只是等到孩子完成(當然,他的沒有變化,因爲對於父母什麼也沒有發生 - 只有等待
  7. 當孩子(ls -l)完成時,父母的contienue運行 - 當然, $#是沒有理由改變...

ps:以上是簡單的。事實上,他們沒有完全分叉後相同但不同在一個數字 - 父母得到孩子的進程號碼,這個孩子的這個孩子有'0'

0

我不認爲$#適用於交互式shell。它在腳本中工作正常。嘗試這個。

$ cat try.sh 
#!/bin/bash 
echo $* 
echo $# 

$ ./try.sh one 
one 
1 

$ ./try.sh one two 
one two 
2 

$ ./try.sh one two three 
one two three 
3 
1

如果環境變量是全球性的,爲什麼不是4 1

我相信你會問,爲什麼運行該命令ls -l位置參數不會改變從四比一與一個是-l

它確實將它們設置爲-l的程序ls。當程序ls查詢其位置參數時,它被告知具有由-l組成的單個參數。但是,一旦ls終止,位置參數將返回到之前的狀態。

如果環境變量是全球性的,

即使是全球性的環境變量,子進程改變他們從未出現父進程。環境變量的傳播是單向的:僅從父母到孩子。

例如:

$ cat test1.sh 
echo "in $0, before, we have $# pos. params with values=$*" 
bash test2.sh calling test2 from test1 
echo "in $0, after , we have $# pos. params with values=$*" 

$ cat test2.sh 
echo "in $0, we have $# pos. params with values=$*" 

$ bash test1.sh -l 
in test1.sh, before, we have 1 pos. params with values=-l 
in test2.sh, we have 4 pos. params with values=calling test2 from test1 
in test1.sh, after , we have 1 pos. params with values=-l 

而且,另一個例子,這一次顯示,一個孩子對環境變量的改變不會影響父:

$ cat test3.sh 
export myvar=1 
echo "in $0, before, myvar=$myvar" 
bash test4.sh 
echo "in $0, after, myvar=$myvar" 

$ cat test4.sh 
export myvar=2 
echo "in $0, myvar=$myvar" 

$ bash test3.sh 
in test3.sh, before, myvar=1 
in test4.sh, myvar=2 
in test3.sh, after, myvar=1 
+0

謝謝,我對ENV變量的理解完全錯誤。 – khajvah

+0

使用'「values = $ *」'示範性地不是最佳實踐 - 它將'foo「」bar「與」foo bar「混合在一起。 'printf'%q'「$ @」'明確區分這個區別,因爲(在較小的範圍內)確實如'printf'<%s>'「$ @」'。 –

相關問題