舉例說明Linux shell中local、export的常用用法和要注意的問題


一、前言

  在【Linux shell】中,【local】和【export】通常被拿來控制shell中變量的作用域。export被用到的場合會更多一些,local只能被用在shell函數中。

 

二、直接上例子

  為了方便理解,嘗試寫三個簡單的shell腳本。

  命令【yjcmd】:首先用shell模擬一個有輸出的,返回值為錯誤值的命令。

  shell【yjshell.sh】:寫一個【local】、【export】和【默認shell變量】放在一起對比的【例子shell】。

  子shell【yjchildshell.sh】:為了表達變量在shell間傳遞,寫一個【子shell】,【子shell】中嘗試訪問【yjshell.sh】中的【三種】類型的變量。

 

  1、【yjcmd】

    

    這個命令的作用是輸出【yjtest】,並且返回【1】,代表命令執行錯誤。

 

  2、【yjshell.sh】

    

 

  3、【yjchildshell.sh】

    

 

三、執行結果

     

    注:【bash】和【dash】中,結果都如上圖所示,沒有差別。

 

四、基本規律總結

  基本規律大多數常寫shell腳本的人都非常清楚,這里不過多討論,簡單總結下。

  從【三、】的執行結果中可以清晰看出:

  1、默認變量可以在【yjshell.sh】的任意位置訪問到,但是【不能】被【子shell】【yjchildshell.sh】繼承。

  2、被【local修飾】的變量只在【當前shell函數】中生效,【yjshell.sh】的其它地方並不能得到這個變量的值,並且【子shell】也無法繼承它。

  3、被【export修飾】的變量其實已經成為了【當前shell】的【環境變量】,可以被【當前shell】以及【當前shell調用的子shell】訪問到。

  注:雖然export修飾的變量【作用范圍變大】,但是其僅限於【當前shell環境】和【被其調用的子shell】中,並不能影響到其【父shell】(這里例子沒有展示,簡單來說就是當前shell環境中export的內容,當前shell的父shell無法訪問)。

 

五、例子中的坑

  我們可以看到例子中,關於函數內的打印,多了一個【$?】的輸出,【$?】是用來獲取上一條命令執行結果值的。

  可以看到【yjcmd】這個命令中,命令的輸出內容是【yjtest】,命令的返回值是【1】,想要表達這個命令執行出錯了,返回了錯誤值。

  通常情況下,shell腳本中的變量賦值並不會影響【$?】的數值,因為變量賦值不屬於命令范疇。

  但是當命令執行的輸出被賦值給三種類型變量后,【$?】的輸出卻並不相同。

 

六、關於坑的探索

  出現這個問題的初期,確實挺令人不解的,明明只是幾個不同作用域的變量,被【yjcmd】命令的輸出賦了值,為何會導致后續的【$?】命令取值發生了變化。

  帶着這個問題探索了很長時間的百度,並沒有什么收獲。

  后來回歸【local】和【export】的定義時,被“點醒”了。

  【local】和【export】的定義中,對【local】和【export】的名詞定性為【命令】。

  我們都知道,當描述一個物體時,通常會用形容詞+名詞的方式進行表達,形容詞通常用來說明這個【物體的性質】,名詞用來表達這個【物體的本質】。

  例如面試中最為經典的【指針數組】和【數組指針】的概念區分,英文描述中借助的就是這個原理,用名詞部分區分這兩個概念的本質。

  既然【local】和【export】的本質被定義為【命令】,那么這就代表【local】和【export】就具備了命令的通用特性,具備【返回值】。

  所以說例子中,命令執行,命令輸出被賦值給了變量,變量被【local】和【export】修飾相當於執行了一條命令。

  換句話說,被修飾的變量作用域縮小或是擴大是【local】和【export】命令作用的結果,因此【$?】的值就是【local】和【export】命令執行的返回值。

  因此也就可以解釋為什么【yjcmd】明明返回的是【1】,但是【$?】的輸出確實【0】了。

 

七、關於坑的總結

  這個小小的問題如果不被關注,可能會導致一個巨大的bug,這里記錄下來用來給自己提個醒。

  需要獲取命令執行成功與否時,如果想通過返回值的方式進行判斷,那么就不要將命令的輸出【直接賦值】給【local】【export】修飾的變量。

  如果必須要【直接賦值】給【local】或【export】修飾的變量,那就嘗試通過【命令輸出】判斷命令執行的結果,而不是通過【$?】來判斷。

  


免責聲明!

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



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