1)變量類型
1)變量可分為倆類:環境變量(全局變量),和普通變量(局部變量),
環境變量也稱為全局變量,可以在創建他們的Shell及其派生出來的任意子進程Shell中使用,環境變量又可以分為自定義環境變量和bash內置的環境變量,環境變量可以在命令行中設置和創建,用戶退出命令行時這些變量值就會丟失,想要永久保存環境變量,可在用戶家目錄下的. bash_profile或. bashrc(非用戶登錄模式特有,如:SSH)文件中,或在/etc/profile文件中定義,這樣每次用戶登錄時這些變量都將被初始化。
普通變量也可成為局部變量,只能在創建它們的Shell函數或Shell腳本中使用,普通變量一般由開發者在開發腳本程序時創建,
2)查看設置的變量
set命令輸出所有的變量,包括全局變量和局部變量
1 [root@king ~]# set
2 APACHEERR=hello world 3 BASH=/bin/bash 4 BASH_ALIASES=() 5 BASH_ARGC=() 6 BASH_ARGV=() 7 BASH_CMDS=() 8 BASH_LINENO=() 9 BASH_SOURCE=() 10 BASH_VERSINFO=([0]="4" [1]="1" [2]="2" [3]="1"
11 中間和結尾省略若干代碼
env(printenv)命令只顯示全局變量,
1 [king@king~]$ env 2 HOSTNAME=king 3 SHELL=/bin/bash #大家可以自行查看一下哦
declare命令輸出所有的變量,函數,整數,和已經導出的變量,set -o命令顯示bashShell的所有參數配置信息
3)自定義環境變量
如果想設置環境變量,就要給在給變量賦值后或在設置變量時使用export命令,export命令和declare命令的格式:
- export 變量名=value
- 變量名=value ; export 變量名
- declare - x 變量名=value
小試牛刀:定義環境變量並賦值的方法:
- export NAME=qzlking
- declare -x NAME=qzlking
- NAME=qzlking ; exprot NAME
1 [root@king script]# cat /etc/profile|grep qzl 2 export qzl='qzlking' #<==編輯/etc/profile,然后輸出此行並保存 3 [root@king script]# source /etc/profile #<==或./etc/profile使其生效 4 [root@king script]# echo $qzl #<==在變量前加$符號並打印變量值 5 qzlking 6 [root@king script]# env|grep qzl #<==查看定義結果 7 qzl=qzlking
我們一起來看一下讓環境變量永久生效的常用配置文件
a)用戶環境變量配置
1 [root@king scripts]# ls /root/.bashrc 2 /root/.bashrc 3 [root@king scripts]# ls /root/.bash_profile 4 /root/.bash_profile
說明:對於用戶的環境變量設置,常見的是用戶家目錄下的.bashrc和.bash_profile。
b)全局環境變量的配置
常見的全局環境變量配置文件,/etc/profile;/etc/bashrc;/etc/profile.d這三個配置文件,如果想要在登陸后初始化或者顯示加載的內容,只需要把腳本文件放在/etc/profile.d文件下即可(不需要加執行權限)。
在Java環境中,自定義環境變量,通常放在/etc/profile全局環境變量里哦,
1 export JAVA_HOME=/application/jdk 2 export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib 3 export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH:$HOME/bin 4 export RESIN_HOME=/application/resin
4)查看/取消環境變量
我們通常在工作中要查看一下環境變量中都配置了什么,需要做什么更改,所以我們就有了ehco或printf命令來打印查看環境變量。
- $HOME:用戶登錄時進入的目錄
- $UID:當前用戶的uid( 也就是用戶的標識,相當於人的身份證)相當於id -u
1 [king@king ~]$ echo $HOME 2 /home/king 3 [king@king ~]$ echo $UID 4 300
我們可以用unset來消除本地變量和環境變量
1 [king@king ~]$ echo $USER 2 nane 3 [king@king ~]$ unset $USER 4 [king@king ~]$ echo $USER #<這里輸出是個空行 5
小結:
- 變量名一定要大寫,可以在自身的Shell及子Shell中使用,常用export來定義環境變量
- 執行enc默認可以顯示所有的環境變量名稱及對應的值
- 輸出時用“$變量名”,取消用“unset 變量名”
2)環境變量初始化與對應文件的生效順序
1.登陸Shell讀取環境變量文件的流程

用戶登錄系統后首先會加載/etc/profile全局環境變量文件,加載完后,執行/etc/profile.d目錄下的腳本文件(如:系統的字符集設置/etc/sysconfigil8n),然后在運行$HOME/.bash_profile(用戶環境變量文件),在這文件里會找$HOME/.bashrc(用戶環境變量文件),有就執行,沒有就不執行。在$HOME/.bashrc找/etc/bashrc(全局環境變量文件)有就執行,沒有就不執行。如果希望用戶的Shell不是登陸時啟動的(如:手動敲下bash時啟動或者遠程ssh連接情況),非登陸Shell只會加載$HOME/.bashrc(用戶環境變量文件),並會去找/etc/bashrc(全局環境變量文件)。即非登陸Shell想讀到設置的環境變量,需要將變量設定等寫入$HOME/.bashrc(用戶環境變量文件)或etc/bashrc(全局環境變量文件)不是$HOME/.bash_profile或/etc/profile。。。
3)定義本地變量
1)普通變量的定義,有三種寫法
- 變量名=value #不加引號時,值里有變量的會被解析后輸出。
- 變量名='value' #輸出變量內容時單引號里是什么就輸出什么,不管什么都原樣輸出。
- 變量名="value" #輸出變量內容時引號里的變量和命令經過解析后輸出。
2)命令結果作為的變量內容來賦值
- 變量名=`mkdir` #這里是反引號,
- 變量名=$(mkdir) #把命令$()括起來,來賦值。

4)變量定義的技巧總結
- 變量名只能為字母,數字或者下划線,只能以字母或下划線開頭,要見名知意。
- 一般變量的定義,賦值常用雙引號,希望原樣輸出的加單引號。
- 希望變量的內容是命令的解析結果時,要用反引號``,或者用$()把命令括起來在賦值
- 打印輸出或使用變量時,變量名前要接$符號。
變量定定義示例:
1 KingAge=25 #<==每個單詞的首字母大寫的寫法 2 king_age=25 #<==單詞之間用"_"的寫法 3 kingAgeSex=25 #<==駝峰語法: 首個單詞的首字母小寫,其余單詞首字母大寫 4 kingAGE=25 #<==單詞全大寫的寫法
5)Shell特殊位置變量
Shell中存在一些特殊且重要的變量,如下
- $0 獲取當前執行Shell腳本的文件名字,如果執行腳本時候加了路徑,那就包含腳本路徑跟腳本名字一起輸出
- $n 獲取當前執行Shell交本的第n個參數,n=1..9,n>9,后面參數變量就需要用大括號,如:${10},以空格分隔
- $# 獲取當前執行Shell腳本接了多少個參數(總計)
- $* 獲取當前執行Shell腳本所有傳參的參數
- $@ 獲取當前執行Shell腳本所有傳參的參數($*和$@詳解見例子)
1 [root@ king tmp]# cat t.sh
2 if [ $# -ne 2 ] #如果執行腳本傳參的個數不為2,
3 then
4 echo "USAGE:/bin/sh $0 arg1 arg2" #則給用戶提示正確用法,此處的$0,打印腳本名字及路徑。
5 exit 1 #若不滿足要求,則退出腳本,返回值為1。
6 fi
7 echo $1 $2 #若參數滿足要求,則打印$1和$2獲取到的傳參的字符串。
8 [root@ king tmp]# sh t.sh #若不加參數執行腳本,則直接給出提示。
9 USAGE:/bin/sh t.sh arg1 arg2 #t.sh就是腳本中$0獲取的值。
10 [root@ king tmp]# sh t.sh hello world
11 hello world #若參數滿足要求,則打印$1和$2獲取的字符串,即hello和world。
$0,$n,$#,這幾個就不多說了,因為太好理解了,下面我們來一起學習一下$*和$@的區別吧。
我們可以利用set 來設置位置參數Age of loss
1 [root@king tmp]# set -- "This is" Age of loss. #“--”表示清除所有的參數變量,重新設置后面的參數變量。
2 [root@king tmp]#echo $# #輸出參數的個數。
3 3 #共三個參數。
4 [root@king tmp]# echo $1 #打印第一個參數值。
5 This is
6 [root@king tmp]# echo $2 #打印第二個參數值。
7 Age
8 [root@king tmp]# echo $3 #打印第三個參數值。
9 of
10 [root@king tmp]# echo $4 #打印第四個參數值。
11 loss.
12 #測試$*和$@,注意,此時不帶雙引號:
13 [root@king tmp]# echo $* #打印$*。
14 This is Age of loss.
15 [root@king tmp]# echo $@ #打印$@。
16 This is Age of loss.
17 [root@king tmp]# for i in $*; do echo $i; done #使用for循環輸出$*測試。
18 This #($*)不加雙引號,因此會輸出所有參數,然后第一個參數"This is"也拆開輸出了。
19 is
20 Age
21 of
22 loss
23 [root@king tmp]# for i in $@; do echo $i; done #使用for循環輸出$@測試。
24 This #($@)不加雙引號,因此會輸出所有參數,然后第一個參數"This is"也拆開輸出了。
25 is
26 Age
27 of
28 loss
29 #測試"$*"和"$@",注意,此時帶有雙引號:
30 [root@king tmp]# echo "$*"
31 This is Age of loss.
32 [root@king tmp]# echo "$@"
33 This is Age of loss.
34 [root@king tmp]# for i in "$*"; do echo $i; done
35 This is Age of loss. #在有雙引號的情況下"$*",參數里引號中的內容當作一個參數輸出了!
36 [root@king tmp]# for i in "$@"; do echo $i; done
37 This is #在有雙引號的情況下,每個參數均以獨立的內容輸出,且有雙引號算一個參數。
38 Age
39 of
40 loss
41 #這才真正符合我們傳入的參數需求,set -- "This is" Age of loss.
6)Shell特殊狀態變量
Shell特殊狀態變量
- $? 獲取執行上一個指令的執行狀態返回值(0成功,非0為失敗)
- $$ 獲取當前執行Shell腳本的進程號(PID)
- $! 獲取上一個在后台工作的進程的進程號(PID)
- $_ 獲取在此之前執行的命令或腳本的最后一個參數
$?特殊變量,根據返回值來判斷備份成功於否,例子
1 [root@king tmp]# cd /etc/
2 [root@king etc]# tar zcf /opt/services.tar.gz ./services #打包備份
3 [root@king etc]# echo $? #檢查備份后的,返回0表示打包成功,
4 0
我們可以查看一下NFS網絡文件共享系統/etc/init.d/rpcbind腳本中的50-73行吧,學習一下$?使用,
1 [root@king scripts]# sed -n '63,73p' /etc/init.d/rpcbind #sed -n 打印文件指定行、
2 stop() {
3 echo -n $"Stopping $prog: "
4 killproc $prog #這是停止rpcbind的命令。
5 RETVAL=$? #將上述命令的返回值“$? ”賦值給RETVAL變量,用於后面的判斷。
6 echo
7 [ $RETVAL -eq 0 ]&&{ #這里就是判斷,如果返回值為0,則執行下面的指令。
8 rm -f /var/lock/subsys/$prog
9 rm -f /var/run/rpcbind*
10 }
11 return $RETVAL #如果返回值不等於0,則跳過判斷,直接作為返回值傳給執行stop函數的腳本。
12 }
$?返回值的用法總結:
- 判斷命令,腳本或者函數等程序是否執行成功
- 若在腳本中調用執行“exit 數字”,則會返回這個數字給“$?”變量
- 如果是在函數里,則通過“return 數字”,把這個數字以函數返回值的形式傳給“$?”
7)Shell特殊擴展變量
Shell特殊位置變量
我們可以man bash 命令,然后搜索"Parameter Expansion"來查找相關的內容幫助
- ${parameter:-word} 如果parameter的變量值為空或沒賦值,則返回word字符串並代替變量的值(變量沒定義,返回備用的值,防止變量為空或沒定義報錯)
- ${parameter:=word} 如果parameter的變量值為空或沒賦值,。。。同上,(變量沒定義為防止出錯,找的備胎變量)
- ${parameter:?word} 如果parameter的變量值為空或者沒賦值,word字符串就作為標准錯誤輸出,否則出書變量的值(捕捉由於變量未定義導致的錯誤,並退出)
- ${parameter:+word} 若果parameter的變量值為空或者未賦值,則什么都不做,否則word字符串將代替變量的值。
${parameter:-word}用法距離:沒有賦值的情況
1 [root@king tmp]# echo $test #變量未設置,所以輸出時為空。
2 [root@king tmp]# result=${test:-UNSET} #<==若test沒值,則返回UNSET。
3 [root@king tmp]# echo $result #打印result變量,返回UNSET,因為test沒有賦值。
4 UNSET
5 [root@king tmp]# echo ${test} #注意,此時打印test變量還是為空。
結論:對於${test:-UNSET},當test變量沒值時,就返回變量結尾設置的UNSET字符串。
賦值的情況
1 [root@king tmp]# test=hello #賦值hello字符串。
2 [root@king tmp]# echo $test
3 hello
4 [root@king tmp]# result=${test:-UNSET}
5 [root@king tmp]# echo $result #因為test已賦值,因此,打印result就輸出了test的值hello,而不是原來的UNSET。
6 hello
7 [root@king tmp]# result=${test-UNSET} #定義時忽略了冒號。
8 [root@king tmp]# echo $result
9 hello #打印結果和帶冒號時沒有變化。
${parameter:=word}和${parameter:-word}差不多,理解都是一樣的,變量為賦值就把備胎給變量。。。
${parameter:?word}變量為賦值或空,就將該字符串(word)作為標准錯誤輸出。
1 [root@king tmp]# echo ${key:? not defined} #key變量沒有定義,因此,把“not defined”作為標准錯誤輸出。
2 -bash: key: not defined #錯誤提示,只不過是事先定義好的錯誤輸出。
3 [root@king tmp]# echo ${key? not defined} #去掉冒號定義,並輸出,結果一致。
4 -bash: key: not defined
5 [root@king tmp]# key=5 #<==給變量賦值1。
6 [root@king tmp]# echo ${key:? not defined} #因為key有值了,所以,打印key的值。
7 5
8 [root@king tmp]# echo ${key? not defined} #去掉冒號定義,並輸出,結果一致。
9 5
10 [root@king tmp]# unset key #取消key的定義。
11 [root@king tmp]# echo ${key:? not defined}
12 -bash: key: not defined #又打印錯誤提示了。
${parameter:+word}變量為空或沒賦值,什么都不做,否則用word字符串替換變量的值
1 [root@king tmp]# key=${value:+word} #value變量未定義。
2 [root@king tmp]# echo $key #因為value變量未定義,所以打印key變量為空。
3 [root@king tmp]# value=25 #value變量賦值為25。
4 [root@king tmp]# key=${value:+word} #注意,這里一定要重新定義key。
5 [root@king tmp]# echo $key
6 word #因為value變量有值,所以打印key變量輸出為“:+ ”后面的內容。
