shell 編程(四):變量
阿新 • • 發佈:2018-04-17
shell bash 變量 declare set 變量
變量是能儲存計算結果或能表示值抽象概念。變量可以通過變量名訪問。
變量聲明
聲明變量一般使用下面方式:
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 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 只讀變量
-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:~#
變量調用
在聲明變量一個變量時變量名稱要遵守下列規則:
- 不能以特殊字符(除了_),數字,美元符($)開頭
- 變量名不能是純數字
- 變量名可以是英文或數字或特殊字符(_)的組合
調用變量時在變量明前面以$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:~#
參考資料
- Linux中 set、env、declare、export顯示shell變量的區別
shell 編程(四):變量