Linux shell 編程(四):變量

變量

變量是能儲存計算結果或能表示值抽象概念。變量可以通過變量名訪問。

變量聲明

聲明變量一般使用下面方式:

root@iZuf6ilzd4iqvuj4dvuiwtZ:~# var=test #這裏聲明瞭一個名爲 var 的變量,並給他賦值爲test
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# # “=”前後不能有空格,變量名區分大小寫

或者下面方式:

root@iZuf6ilzd4iqvuj4dvuiwtZ:~/HtmlDOM/Libs# declare var1=123
root@iZuf6ilzd4iqvuj4dvuiwtZ:~/HtmlDOM/Libs# export var2=234
root@iZuf6ilzd4iqvuj4dvuiwtZ:~/HtmlDOM/Libs# 
root@iZuf6ilzd4iqvuj4dvuiwtZ:~/HtmlDOM/Libs# env var3=333

上面使用的命令:declare,export,env 都可以聲明變量,區別在於變量作用域不同。
shell有兩種變量:

  • shell局部變量
    局部變量在腳本或命令中定義,僅在當前shell實例中有效,其他shell啓動的程序不能訪問局部變量。
    通過賦值語句定義好的變量,可以通過如下方法定義shell變量
    root@iZuf6ilzd4iqvuj4dvuiwtZ:~/HtmlDOM/Libs# declare var1=123
    root@iZuf6ilzd4iqvuj4dvuiwtZ:~/HtmlDOM/Libs# var1=123

  • 用戶環境變量
    所有的程序,包括shell啓動的程序,都能訪問環境變量,有些程序需要環境變量來保證其正常運行。必要的時候shell腳本也可以定義環境變量。
    通過export語法導出的shell私有變量,可以通過如下方法導出用戶環境變量
    export x =2
    declare -x x=2

變量使用

顯示shell變量

  • env 這是一個工具,或者說一個Linux命令,顯示用戶的環境變量。
  • set 顯示用戶的局部變量和用戶環境變量。
  • export 顯示導出成用戶變量的shell局部變量,並顯示變量的屬性;就是顯示由局部變量導出成環境變量的那些變量 (比如可以 export WWC導出一個環境變量,也可通過 declare -X LCY導出一個環境變量)
  • declare 跟set一樣,顯示用戶的shell變量 (局部變量和環境變量)

declare命令:

    # 語法:declare [-aAfFgilnrtux] [-p] [name[=value] ...]
    # 描述: declare 用來聲明變量和配置變量的屬性,如果declare後面沒有參數,將會顯示全部變量的屬性和值。
    # 參數
                -f   限制行動或顯示函數名稱和定義
                -F  只限制顯示函數名(加上行號和源文件時調試)
                -g  在shell函數中使用時創建全局變量;否則忽略
                -p  顯示每個變量的屬性和值。

    # 屬性設置參數
                -a  聲明一個索引數組
                -A  聲明一個聚合數組
                -i   變量值爲整數,當給變量賦值爲非整數值時變量爲0
                -l   給變量賦值時轉換成小寫字母
                -n  將名稱引用爲其值命名的變量。
                -r   只讀變量 # 使用readonly命令也可以設置變量只讀
                -t  使名稱具有“trace”屬性
                -u  給變量賦值時轉換成大寫字母
                -x  導出變量到用戶環境變量

export命令

    # 語法: export [-fn] [name[=value] ...] or export -p
    # 描述:從shell變量導出屬性,將自動導出的每個名稱標記爲隨後執行的命令的環境。如果提供了值,則在導出之前分配值。
    # 參數
     -f     引用shell函數
     -n     從每個變量刪除導出屬性
     -p     顯示已導出的函數和變量清單

set 命令

    # 語法:set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
    # 描述:設置或取消shell參數和位置參數的值。更改shell屬性和位置參數的值,或顯示shell變量的名稱和值。

    # 參數:
      -a  標記爲導出而修改或創建的變量。
      -b  立即通知終止任務。
      -e  如果有非零狀態的命令退出,立即退出。
      -f  禁用文件名稱生成(全局)。
      -h  記住所查找的命令位置。
      -k 所有的賦值參數都放置在一個命令的環境中,而不僅僅是在命令名前面的命令。
      -m  開啓任務控制。
      -n  讀取命令,但不執行它們。
      -o option-name
          設置對應於選項名的變量:
              allexport    與-a相同
              braceexpand  與-B相同
              emacs        使用emacs樣式的行編輯界面。
              errexit      與-e相同
              errtrace     與-E相同
              functrace    與-T相同
              hashall      與-h相同
              histexpand   與-H相同
              history      開啓命令歷史
              ignoreeof    讀取EOF時shell不會退出
              interactive-comments
                           允許註釋出現在交互式命令行中
              keyword      same as -k
              monitor      same as -m
              noclobber    same as -C
              noexec       same as -n
              noglob       same as -f
              nolog        目前接受但忽略
              notify       same as -b
              nounset      same as -u
              onecmd       same as -t
              physical     same as -P
              pipefail     管道的返回值是最後一個以非零狀態退出的命令的狀態,如果沒有非零狀態的命令退出,則爲零。
              posix        更改bash的行爲,默認操作與Posix標準不同,以匹配標準。
              privileged   same as -p
              verbose      same as -v
              vi           使用vi樣式的行編輯界面
              xtrace       same as -x
      -p  當真實有效的用戶id不匹配時打開。取消對$ENV文件的處理和shell函數的導入。關閉這個選項會導致有效的uid和gid設置爲真正的uid和gid。
      -t  讀取和執行一個命令後退出。
      -u  在替換時將未設置的變量視爲一個錯誤。
      -v  打印shell的輸入行。
      -x  打印命令及其執行時的參數。
      -B  shell將執行支撐擴展
      -C  如果設置,則不允許通過重定向輸出來覆蓋現有的常規文件。
      -E  如果設置,ERR捕獲是由shell函數繼承的。
      -H  啓用!風格歷史替換。當shell是交互式的時,這個標誌是默認的。
      -P  如果設置,在執行命令(例如更改當前目錄的cd)時,不要解析符號鏈接。
      -T  如果設置,DEBUG捕獲從shell函數繼承
      --  將剩餘的參數分配給位置參數。如果沒有剩下的參數,那麼位置參數就沒有設置。
      -   將剩餘的參數分配給位置參數。-x和-v選項關閉。

env命令

    # 描述: 在修改的環境中運行程序,將每個名稱設置爲環境中的值並運行命令。對長參數的強制參數也必須是短參數。
    # 語法: env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
    # 參數
        -i, --ignore-environment
              從一個空的環境開始。

        -0, --null
              用NUL,而不是newline結束每個輸出行。

        -u, --unset=NAME
              從環境中刪除變量。

    # 如果沒有參數則打印當前環境中的變量

變量作用域

shell變量

shell變量相當於一個全局變量,可以在子shell,函數中使用。在函數中直接聲明一個變量或者使用declare -g 聲明變量,則此變量爲全局變量。

如:

# variable=value
# declare variable=value

函數變量

使用local命令可以聲明一個函數(局部)變量,此變量只能在函數內訪問,如果不適用local命令,則此變量爲shell(全局)變量。

function test(){
    variable=123; # 全局變量
    declare -g v=2 # 全局變量
    local a=123 # 函數(局部)變量,只能在函數內訪問
}

變量取消

使用unset命令可以刪除變量

unset命令

    # 語法: unset [-f] [-v] [-n] [name ...]
    # 描述: 撤銷shell變量和函數的值和屬性。對於每個名稱,刪除相應的變量或函數。
    # 參數:
        -f  將name參數視爲函數
        -v  將name參數視爲變量
        -n  每個名稱視爲一個名稱引用,並將變量本身設置爲unset。而不是它引用的變量。
        # 沒有選項,unset首先嚐試取消設置一個變量,如果失敗,則嘗試取消設置一個函數。
        # 注意:只讀變量不能被unset
        root@iZuf6ilzd4iqvuj4dvuiwtZ:~# declare -r NAME=raojl
        root@iZuf6ilzd4iqvuj4dvuiwtZ:~# unset NAME
        -bash: unset: NAME: cannot unset: readonly variable
        root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

變量調用

在聲明變量一個變量時變量名稱要遵守下列規則:

  1. 不能以特殊字符(除了_),數字,美元符($)開頭
  2. 變量名不能是純數字
  3. 變量名可以是英文或數字或特殊字符(_)的組合

調用變量時在變量明前面以$var的形式調用變量,如:

root@iZuf6ilzd4iqvuj4dvuiwtZ:~# name=raojl # 聲明一個名爲name的變量並賦值爲raojl
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo $name # 調用變量name
raojl  # name的值
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

變量名可以在雙引號""內使用,shell會解釋引號內的變量,在''則不會解釋變量。如:

root@iZuf6ilzd4iqvuj4dvuiwtZ:~# name=raojl
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo "$name" # shell會解釋引號內的變量name
raojl # 變量name的值
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo '$name' # shell不會解釋name
$name # 原樣輸出,不會解釋
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

也可以使用大括號${variable}的形式將變量包裹起來,爲了避免變量名被其他字符干擾,可以使用此方式,如:

root@iZuf6ilzd4iqvuj4dvuiwtZ:~# hello=Hello
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo "$helloWorld" # shell將會解釋變量 hellworld

root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo "${hello}World" # shell將會解釋hello變量
HelloWorld
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo "$hello World" 
Hello World
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

$符號引入了參數擴展、命令替換或算術擴展。要擴展的參數名稱或符號可以用括號括起來,這是可選的,但可以保護變量,使其從可以被解釋爲名稱的一部分的字符中擴展。

參數擴展

       ${parameter}
              參數的值被替換。當參數是一個超過一個數字的位置參數時,或者在參數後面加上一個不被解釋爲其名稱的部分的字符時,需要使用括號。參數是一個
              列:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH}
                /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${parameter:-word}
              使用默認值,如果parameter未定義或值爲空則被替換成word,否則爲parmeter的值
              列:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH:-w} #PATH不爲空
                /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PAT:-w} # PAT爲空
                w
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${parameter:=word}
              給parameter賦值默認值,如果parameter爲空或未定義,則將word賦值給parmaeter,否則值不變,parameter的值不變。特殊字符和位置參數不適用
              列:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PAT:=w}
                w
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PAT}
                w
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH:=W}
                /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${parameter:?word}
              如果parameter未定義或爲空,則在輸出(標準錯誤)一個錯誤word,否則輸出parameter的值
               列:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${P:?ERROR} # P未定義
                -bash: P: ERROR
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${parameter:+word}
              使用替代值.  如果parameter 爲空或未定義,輸出爲空,否則輸出word
              列:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${P:+ERROR}

                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH:+ERROR}
                ERROR
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${parameter:offset}
       ${parameter:offset:length}
              子字符串擴展,從offset位置開始,輸出length個字符
            如果偏移量計算爲小於零的數,則該值用作參數值結束時字符的偏移量。
            如果長度對小於零的數求值,則將其解釋爲從參數值(而不是多個字符)結
            束字符的偏移量,而擴展是偏移量與結果之間的字符。注意,一個負偏移
            量必須與冒號隔開至少一個空間。
                如果length未指定,則0-offset位置的字符將會被刪除
              如果參數是@,那麼結果就是長度位置參數開始偏移。相對於最大的位
              置參數,一個負偏移量被取走,所以-1的偏移量等於最後一個位置參數
              。如果長度計算爲小於零的數,則爲擴展誤差。

              如果參數是由@或*編寫的索引數組名,則結果是數組的長度成員以${pa
              rameter[offset]}開始。相對於指定數組的最大索引,將使用一個負偏
              移量。如果長度計算爲小於零的數,則爲擴展誤差。

              應用於關聯數組的子字符串擴展會產生未定義的結果。

              子字符串索引是從零開始的,除非使用了位置參數,在這種情況下,在
              默認情況下,索引從1開始。如果偏移量爲0,並且使用了位置參數,$0
              將被預先固定到列表中。
              列:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH:2}
                sr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH:2:4}
                sr/l
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${!prefix*}
       ${!prefix@}
              變量名匹配,匹配以prefix開頭的變量名,輸出匹配的變量名
              列:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${!P*}
                PAT PATH PIPESTATUS PPID PS1 PS2 PS4 PW PWD
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${!P@}
                PAT PATH PIPESTATUS PPID PS1 PS2 PS4 PW PWD
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${!name[@]}
       ${!name[*]}
              數組鍵的列表。如果名稱是一個數組變量,則擴展到名稱中指定的數組
              索引(鍵)列表。如果名稱不是數組,則將其擴展爲0,如果名稱設置爲n
              ull,則爲null。當使用@時,擴展出現在雙引號,每個鍵擴展到一個單獨的單詞。
                例如:
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${name[@]}
                    1 2
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${!name[@]}
                    0 2
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${#parameter}
              變量長度,如果變量未定義或爲空則返回0,如果是一個數組變量則返回數組長度
              例如:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${#PATH}
                60
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${parameter#word}
       ${parameter##word}
              前綴匹配模式,如果parameter的值以word開頭則parameter前的word將會被刪除,如果parameter是一個數組變量,形如${parameter[@]#word},則此數組中的每個值將會與word做前綴匹配

              #word 爲最短匹配
              ##word 爲最長匹配
                例如:
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH#/usr}
                    /local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 
       ${parameter%word}
       ${parameter%%word}
              與${parameter#word}相反,後綴匹配
                例如:
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH%bin}
                    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${parameter/pattern/string}
              模式替換,pttern將被替換成string
              正常情況下pattern 只有第一個匹配的會陪替換成string
              如果表達式以#開頭,如:#w,則必須匹配以w開頭的
              如果表達式以%幾位,如:t%,則必須匹配以t結尾的
              pattern支持通配符*,如:${PWD/*/s},則變量PWD的值全部被替換成s
              如果parameter是一個數組變量,則數組中的成員都會執行此操作,返回一個匹配結果數
                例如:
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH/#\/usr/s}
                    s/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${parameter^pattern}
       ${parameter^^pattern}
       ${parameter,pattern}
       ${parameter,,pattern}
              大小寫轉換.
              ^ 操作將pattern的匹配結果轉換成大寫字母,第一個字符
              , 操作將pattern的匹配結果轉換成小寫字母,第一個字符
              ^^ 操作將pattern的匹配結果轉換成大寫字母
              ,, 操作將pattern的匹配寄過轉換成小寫字母

              如果parameter是一個數組變量,則數組中的每個成員將會與pattern做匹配
              通配符:
                * 在^^和,,操作中表示0個或多個字符,在^和,中表示一個或0個字符
                ? 與*相同
             例如:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${TERM,*} 
                xterm
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${TERM^*} 
                Xterm
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${TERM^^*} 
                XTERM
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${TERM,,*} 
                xterm
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

參考資料

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章