shell變量的作用域



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

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

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

Shell 局部變量

原理 代碼 輸出結果 結論 其他
Shell 支持自定義函數,但是 Shell 函數和其他編程語言函數的一個不同點就是:在 Shell 函數中定義的變量默認也是全局變量,它和在函數外部定義變量擁有一樣的效果。
  1. #!/bin/bash
  2. #定義函數
  3. function func(){
  4. a=99
  5. }
  6. #調用函數
  7. func
  8. #輸出函數內部的變量
  9. echo $a
99 a 是在函數內部定義的,但是在函數外部也可以得到它的值,證明它的作用域是全局的,而不是僅限於函數內部  
要想變量的作用域僅限於函數內部,可以在定義時加上local命令,此時該變量就成了局部變量
  1. #!/bin/bash
  2. #定義函數
  3. function func(){
  4. local a=99
  5. }
  6. #調用函數
  7. func
  8. #輸出函數內部的變量
  9. echo $a
輸出結果為空 輸出結果為空,表明變量 a 在函數外部無效,是一個局部變量 Shell 變量的這個特性和 JavaScript 中的變量是類似的。在 JavaScript 函數內部定義的變量,默認也是全局變量,只有加上var關鍵字,它才會變成局部變量。

Shell 全局變量

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

關注點 操作 對比1 對比2 其他
全局變量的作用范圍是當前shell進程 打開兩個shell窗口,驗證變量作用域

打開一個 Shell 窗口,定義一個變量 b 並賦值為 88,然后打印,這時在同一個 Shell 窗口中是可正確打印變量 b 的值的。


再打開一個新的 Shell 窗口,同樣打印變量 b 的值,但結果卻為空。


 
全局變量的作用范圍是不僅僅當前的 Shell 腳本文件 在當前shell窗口定義變量a,可以被腳本1使用,在腳本1中定義的變量b,可以在腳本2中使用

 a.sh

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

 

b.sh

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

 

這三條命令都是在一個進程中執行的,從輸出結果可以發現,在 Shell 窗口中以命令行的形式定義的變量 a,在 a.sh 中有效;在 a.sh 中定義的變量 b,在 b.sh 中也有效,變量 b 的作用范圍已經超越了 a.sh。

在Shell 窗口,輸入以下命令

a=99

. ./a.sh -->99

在同樣的shell中執行. ./b.sh -->200

shell全局變量的易錯點:

腳本 分析

PARAM_NUMBER=0;

cat "/home/roaddb/test/55.txt" | while read line

do

    let PARAM_NUMBER=${PARAM_NUMBER}+1;

done

echo "${PARAM_NUMBER}"

結果PARAM_NUMBER的值還是0,原因是在進行 cat的過程中, 相當於打開了一個新的shell,變量不在作用范圍。

#!/bin/bash

PARAM_NUMBER=0;

while read line

do

    let PARAM_NUMBER=${PARAM_NUMBER}+1;

done<"/home/roaddb/test/55.txt"

echo "${PARAM_NUMBER}"

PARAM_NUMBER的值是正確的

linux shell中./a.sh , sh a.sh , source a.sh, . ./a.sh的區別

腳本 知識點  
#! /bin/bash
echo "PID of this script: $$"
echo "PPID of this script: $PPID"

echo $$  輸出當前進程號-------->590

 

echo $PPID 輸出父進程號-------->589

 

 
執行方式 結果  
a.sh

報錯bash: a.sh: command not found

 

./a.sh

bash: ./a.sh: Permission denied

需要權限,設置權限為777后執行

PID of this script: 92669

PPID of this script: 590

啟了一個子shell來執行a.sh,所以可以看到PPID of this script: 590

sh ./a.sh 

PID of this script: 92878

PPID of this script: 590

sh a.sh 

PID of this script: 92928

PPID of this script: 590

source ./a.sh 

PID of this script: 590

PPID of this script: 589

在當前shell中執行腳本
source a.sh 

PID of this script: 590

PPID of this script: 589

. ./a.sh

PID of this script: 590

PPID of this script: 589

../a.sh

報錯bash: ../a.sh: No such file or directory

 


  最后要說明的兩點是:

      1. 用sh和source去執行時, 不要求a.sh有可執行權限, 但單獨./a.sh這樣去搞時,需要可執行權限

      2. 大家在開發項目時,經常需要設置環境變量, 當然是用source啊, 確保在當前shell生效

Shell 環境變量

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

環境變量被創建時所處的 Shell 進程稱為父進程,如果在父進程中再創建一個新的進程來執行 Shell 命令,那么這個新的進程被稱作 Shell 子進程。當 Shell 子進程產生時,它會繼承父進程的環境變量為自己所用,所以說環境變量可從父進程傳給子進程。不難理解,環境變量還可以傳遞給孫進程。

注意,兩個沒有父子關系的 Shell 進程是不能傳遞環境變量的,並且環境變量只能向下傳遞而不能向上傳遞,即“傳子不傳父”。

使用env可以查看所有環境變量!!!

創建 Shell 子進程最簡單的方式是運行 bash 命令,如圖 2 所示。

進入Shell子進程
圖2:進入 Shell 子進程
通過exit命令可以一層一層地退出 Shell。

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

[c.biancheng.net]$ a=22       #定義一個全局變量
[c.biancheng.net]$ echo $a    #在當前Shell中輸出a,成功
22
[c.biancheng.net]$ bash       #進入Shell子進程
[c.biancheng.net]$ echo $a    #在子進程中輸出a,失敗

[c.biancheng.net]$ exit       #退出Shell子進程,返回上一級Shell
exit
[c.biancheng.net]$ export a   #將a導出為環境變量
[c.biancheng.net]$ bash       #重新進入Shell子進程
[c.biancheng.net]$ echo $a    #在子進程中再次輸出a,成功
22
[c.biancheng.net]$ exit       #退出Shell子進程
exit
[c.biancheng.net]$ exit       #退出父進程,結束整個Shell會話

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

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

我們一直強調的是環境變量在 Shell 子進程中有效,並沒有說它在所有的 Shell 進程中都有效;如果你通過終端創建了一個新的 Shell 窗口,那它就不是當前 Shell 的子進程,環境變量對這個新的 Shell 進程仍然是無效的。請看下圖:第一個窗口中的環境變量 a 在第二個窗口中就無效。


環境變量也是臨時的,通過 export 導出的環境變量只對當前 Shell 進程以及所有的子進程有效,如果最頂層的父進程被關閉了,那么環境變量也就隨之消失了,其它的進程也就無法使用了,所以說環境變量也是臨時的。

shell配置文件

那如何讓一個變量在所有 Shell 進程中都有效,不管它們之間是否存在父子關系呢?只有將變量寫入 Shell 配置文件中才能達到這個目的!Shell 進程每次啟動時都會執行配置文件中的代碼做一些初始化工作,如果將變量放在配置文件中,那么每次啟動進程都會定義這個變量。修改配置文件可參考《Shell配置文件的加載》《編寫自己的Shell配置文件》。


免責聲明!

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



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