Shell程式設計中的“區域性變數”和“匯出變數”
http://roclinux.cn/?p=1277
為了防止某些網站的惡性轉載,特在每篇文章前加入此資訊,還望讀者體諒。
===
[正文開始]
如果你對子Shell的概念不甚瞭解,如果你對export的用法還沒吃透,如果你不知道Shell如何管理你的變數,請閱讀本文。否則,請複習本文。^_^
情景一:建立一個shell指令碼var1.sh,其內容為:
[rocrocket@rocrocket SHELL]$ cat -n var1.sh 1 #!/bin/bash 2 echo :$myvar: |
然後在終端上執行變數賦值語句並用echo顯示此變數:
[rocrocket@ |
但是當執行var1.sh指令碼,想顯示myvar變數時,情況卻並非你所願:
[rocrocket@rocrocket SHELL]$ bash ./var1.sh :: |
顯然,var1.sh並沒有看到使用者在終端中定義的myvar變數。可見,在終端中設定的變數,在執行的shell指令碼中是無法看到的。
情景二:我們建立一個指令碼var2.sh,內容為:
[rocrocket@rocrocket SHELL]$ cat -n |
此時,使用者在終端設定myvar的值並顯示此值,然後再執行var2.sh,看看結果吧:
[rocrocket@rocrocket SHELL]$ myvar=100 [rocrocket@rocrocket SHELL]$ echo $myvar 100 [rocrocket@rocrocket SHELL]$ bash var2.sh :50: |
可見,終端中設定的值,在shell指令碼中是無法改變的;而且,終端也無法改變shell腳本里面設定的變數的值。
階段總結:
在Shell工作機制中,存在一個子shell的概念,上面的兩個情景展現的就是子shell的形象。子shell是登入shell為了執行某個指令碼程式而建立的一個全新的shell,這個全新的shell只會使用自己的區域性變數,對父shell(登入shell)的區域性變數不屑一顧。而且,子shell和父shell對對方的區域性變數都不會有任何冒犯,井水不犯河水。
引子:
有些事情偏偏是需要子shell和父shell有所互動的,這就需要有一個變數是子shell和父shell都能看到和修改的。這時候,export出現了,它可以“匯出變數”。
情景三:建立一個新的shell指令碼var3.sh,其內容如下:
[rocrocket@rocrocket SHELL]$ cat -n var3.sh 1 #!/bin/bash 2 echo mylocal=$mylocal 3 echo myglobal=$myglobal |
在var3.sh指令碼中,設定了兩個變數,一個是mylocal,表示區域性變數,一個是myglobal,表示全域性變數。
在終端上給此兩個變數賦值,然後執行指令碼程式var3.sh,很明顯,結果如你所願,是空值:
[rocrocket@rocrocket SHELL]$ mylocal=1 [rocrocket@rocrocket SHELL]$ myglobal=2 [rocrocket@rocrocket SHELL]$ bash var3.sh mylocal= myglobal= |
我們針對myglobal執行export來匯出變數,再看看結果:
[rocrocket@rocrocket SHELL]$ export myglobal [rocrocket@rocrocket SHELL]$ bash var3.sh mylocal= myglobal=2 |
看,我們的指令碼程式已經看到了myglobal的值了,看來export將myglobal匯出,真是起到作用了。
階段總結:
他的內幕是這樣的:當使用export來匯出一個變數時,當前shell就會將此變數放到“匯出變數列表”中,一旦在某個時刻需要建立子shell時,就會將這個匯出變數列表拷貝一份給子shell,這樣子shell也就有所應當的看到了這些被匯出的變量了。
(為了能讓10歲以前小朋友看懂,更形象的說:從前有個母親叫shell,shell她手裡攥著“匯出變數列表”和“區域性變數列表”兩件寶貝,當shell生育了小孩(名叫子shell)的時候,她就把“匯出變數列表”這件寶貝複製一份,交給她的孩子,而shell手裡的另一件寶貝“區域性變數列表”則不會交給小孩)
引子:
現在子shell如果想改變這份“匯出變數列表”中的某些內容,那麼父shell到底能不能察覺呢?父shell會不會隨著子shell一起修改這些值呢?
情景四:看看整個過程:
[rocrocket@rocrocket SHELL]$ export myglobal=10 [rocrocket@rocrocket SHELL]$ cat -n var4.sh 1 #!/bin/bash 2 myglobal=33 3 echo myglobal=$myglobal [rocrocket@rocrocket SHELL]$ bash var4.sh myglobal=33 [rocrocket@rocrocket SHELL]$ echo $myglobal 10 |
可見,在子shell是無法改變父shell中的“匯出變數列表”中變數的值的。子shell只能修改自己手裡的那份“匯出變數列表”中變數的值。
階段總結:
子shell是無法改變父shell中的“匯出變數列表”中變數的值的。
變數一旦被匯出,對所有後續執行的子shell,該變數都是匯出變數。
關於export -p:
可以執行export -p來檢視當前shell的匯出變數列表。這其中一定是包括了從父shell繼承來的匯出變數列表。
全文總結:
1 沒有匯出的變數是區域性變數,子shell是看不到的。
2 匯出變數列表被複制給子shell,子shell可以修改和存取它,但是這種修改父shell看不到。
3 匯出變數列表的上述特性對於直接產生的子shell生效,對於由子shell產生的後繼子shell也是如此。
4 export可以在變數賦值之後用,也可以在變數賦值之前用。
over~