Shell 全局變量、環境變量和局部變量


Shell 變量的作用域(Scope),就是 Shell 變量的有效范圍(可以使用的范圍)。

在不同的作用域中,同名的變量不會相互干涉,就好像 A 班有個叫小明的同學,B 班也有個叫小明的同學,雖然他們都叫小明(對應於變量名),但是由於所在的班級(對應於作用域)不同,所以不會造成混亂。但是如果同一個班級中有兩個叫小明的同學,就必須用類似於“大小明”、“小小明”這樣的命名來區分他們。

Shell 變量的作用域可以分為三種:

  • 有的變量可以在當前 Shell 會話中使用,這叫做全局變量(global variable);
  • 有的變量只能在函數內部使用,這叫做局部變量(local variable);
  • 而有的變量還可以在其它 Shell 中使用,這叫做環境變量(environment variable)。

全局變量

所謂全局變量,就是指變量在當前的整個 Shell 會話中都有效。每個 Shell 會話都有自己的作用域,彼此之間互不影響。在 Shell 中定義的變量,默認就是全局變量。

想要實際演示全局變量在不同 Shell 會話中的互不相關性,可在圖形界面下同時打開兩個 Shell,或使用兩個終端遠程連接到服務器(SSH)。

首先打開一個 Shell 窗口,定義一個變量 a 並賦值為 1,然后打印,這時在同一個 Shell 窗口中是可正確打印變量 a 的值的。然后再打開一個新的 Shell 窗口,同樣打印變量 a 的值,但結果卻為空,如圖 1 所示。
 

打開兩個Shell會話
圖1:打開兩個 Shell 會話


這說明全局變量 a 僅僅在定義它的第一個 Shell 中有效,對其它 Shell 沒有影響。這很好理解,就像小王家和小徐家都有一部電視機(變量名相同),但是同一時刻小王家和小徐家的電視中播放的節目可以是不同的(變量值不同)。

需要強調的是,全局變量的作用范圍是當前的 Shell 會話,而不是當前的 Shell 腳本文件,它們是不同的概念。打開一個 Shell 窗口就創建了一個 Shell 會話,打開多個 Shell 窗口就創建了多個 Shell 會話,每個 Shell 會話都是獨立的進程,擁有不同的進程 ID。在一個 Shell 會話中,可以執行多個 Shell 腳本文件,此時全局變量在這些腳本文件中都有效。

例如,現在有兩個 Shell 腳本文件,分別是 a.sh 和 b.sh。a.sh 的代碼如下:

  1.  
     
  2.  
    #!/bin/bash
  3.  
    echo $a
  4.  
    b=200

b.sh 的代碼如下:

  1.  
    #!/bin/bash
  2.  
    echo $b

打開一個 Shell 窗口,輸入以下命令:

  1.  
    $ a= 99
  2.  
    $ . ./a.sh
  3.  
    99
  4.  
    $ . b.sh
  5.  
    200
  6.  
    $

從輸出結果可以發現,在 Shell 會話中以命令行的形式定義的變量 a,在 a.sh 中有效;在 a.sh 中定義的變量 b,在 b.sh 中也有效。

局部變量

Shell 也支持自定義函數,但是 Shell 函數和 C/C++Java 等其他編程語言函數的一個不同點就是:在 Shell 函數中定義的變量默認也是全局變量,它和在函數外部定義變量擁有一樣的效果。請看下面的代碼:

  1.  
    #!/bin/bash
  2.  
     
  3.  
    #定義函數
  4.  
    function func(){
  5.  
    a=99
  6.  
    }
  7.  
     
  8.  
    #調用函數
  9.  
    func
  10.  
     
  11.  
    #輸出函數內部的變量
  12.  
    echo $a

輸出結果:
99

a 是在函數內部定義的,但是在函數外部也可以得到它的值,證明它的作用域是全局的,而不是僅限於函數內部。

要想變量的作用域僅限於函數內部,那么可以在定義時加上local命令,此時該變量就成了局部變量。請看下面的代碼:

  1.  
     
  2.  
    #!/bin/bash
  3.  
     
  4.  
    #定義函數
  5.  
    function func(){
  6.  
    local a=99
  7.  
    }
  8.  
     
  9.  
    #調用函數
  10.  
    func
  11.  
     
  12.  
    #輸出函數內部的變量
  13.  
    echo $a

輸出結果為空,表明變量 a 在函數外部無效,是一個局部變量。

Shell 變量的這個特性和 JavaScript 中的變量是類似的。在 JavaScript 函數內部定義的變量,默認也是全局變量,只有加上var關鍵字,它才會變成局部變量。

環境變量

全局變量只在當前 Shell 會話中有效,如果使用export命令將它導出,那么它就在所有的子 Shell 中也有效了,這稱為“環境變量”。

環境變量被創建時所處的 Shell 被稱為父 Shell,如果在父 Shell 中再創建一個 Shell,則該 Shell 被稱作子 Shell。當子 Shell 產生時,它會繼承父 Shell 的環境變量為自己所用,所以說環境變量可從父 Shell 傳給子 Shell。不難理解,環境變量還可以傳遞給孫 Shell。

注意,環境變量只能向下傳遞而不能向上傳遞,即“傳子不傳父”。

在一個 Shell 中創建子 Shell 最簡單的方式是運行 bash 命令,如圖 2 所示。
 

進入子 Shell
圖2:進入子 Shell


通過exit命令可以一層一層地退出 Shell。

下面演示一下環境變量的使用:

  1.  
    $ a=22      #定義一個全局變量
  2.  
    $ echo $a    #在當前Shell中輸出a,成功
  3.  
    22
  4.  
    $ bash    #進入子Shell
  5.  
    $ echo $a    #在子Shell中輸出a,失敗
  6.  
     
  7.  
    $ exit    #退出子Shell
  8.  
    exit
  9.  
    $ export a    #將a導出為環境變量
  10.  
    $ bash    #重新進入子Shell
  11.  
    $ echo $a    #在子Shell中再次輸出a,成功
  12.  
    22
  13.  
    $ exit    #退出子Shell
  14.  
    exit
  15.  
    $ exit    #退出父Shell,結束整個Shell會話

可以發現,默認情況下,a 在子 Shell 中是無效的;使用 export 將 a 導出為環境變量后,在子 Shell 中就可以使用了。

export a這種形式是在定義變量 a 以后再將它導出為環境變量,如果想在定義的同時導出為環境變量,可以寫作export a=22

注意,本節我們一直強調的是環境變量在子 Shell 中有效,並沒有說它在所有的 Shell 種有效;如果你通過終端創建一個新的 Shell,那么它就不是當前 Shell 的子 Shell,環境變量對這個 Shell 就是無效的。

此外,通過export命令導出的環境變量是臨時的,關閉 Shell 會話后它就銷毀了。所以,這種環境變量也只是在局部范圍內起作用,並不影響所有 Shell。

如果想讓環境變量在所有 Shell 中都有效,並且能夠永久保存,在關閉 Shell 后也不丟失,那么就需要把環境變量寫入啟動文件。至於如何寫入文件,請大家自行百度,這里就不再贅述了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM