[Linux]shell基礎教程4-變數詳細講解
原創文章,歡迎轉載。轉載請註明:轉載自 祥的部落格
原文連結:https://blog.csdn.net/humanking7/article/details/84641588
文章目錄
環境
ubuntu 16.04
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
1. 概述
變數可分為兩類:環境變數(全域性變數)
普通變數(區域性變數)
。
環境變數
也可稱為全域性變數
,可以在建立它們的Shell
及其派生出來的任意子程序Shell
中使用,環境變數又可分為自定義環境變數
和bash內建的環境變數
。普通變數
也可稱為區域性變數
,只能在建立它們的Shell函式
或Shell指令碼
中使用。普通變數
一般由開發者在開發指令碼程式時建立。
預設情況下,在bash Shell
中是 不會區分變數型別 的,例如常見的變數型別為整數
、字串
等。這和其他強型別語言
(比如C語言
等)是有區別的。當然,如果需要指定Shell變數
的型別,也可以使用declare -p
顯示定義變數的型別,但在一般情況下沒有這個需求。
[email protected]:~# echo $HOME
/root
[email protected]:~# declare -p HOME
declare -x HOME="/root"
2. 環境變數
環境變數
一般是指用export
內建命令匯出的變數(執行export -p
可以檢視)。
所有的環境變數
都是系統全域性變數
,可用於所有子程序
中,這包括編輯器
、Shell指令碼
和各類應用
。
環境變數
可以在命令列
中設定和建立,但使用者退出命令列
時這些變數值就會丟失
,如果希望 永久儲存 環境變數
,可在使用者 家目錄 下的.bash_profile
或.bashrc
(非使用者登入模式
特有,如遠端SSH
)檔案中,或者全域性配置/etc/bashrc
(非使用者登入模式特有
,如遠端SSH
)或 /etc/profile
檔案中定義。在將環境變數
放入上述的檔案中後,每次使用者登入時這些變數
都將被初始化
。
按照系統規範,所有環境變數
的名字均採用大寫形式
。在將環境變數
應用於使用者程序程式之前,都應該用export
命令匯出定義。
有一些環境變數,比如HOME
、PATH
、SHELL
、UID
、USER
等,在使用者登入之前就已經被/bin/login
程式設定好了。通常環境變數被定義並儲存在使用者家目錄下的.bash_profile
檔案或全域性的配置檔案/etc/profile
中。
# 定義一個環境變數 MY_BLOG
[email protected]:~# export MY_BLOG="http://blog.csdn.net/humanking7/"
# 顯示環境變數(中間刪去了一些顯示內容)
[email protected]vultr:~# export -p
declare -x MY_BLOG="http://blog.csdn.net/humanking7/"
declare -x HOME="/root"
declare -x LANG="en_US.UTF-8"
declare -x LESSCLOSE="/usr/bin/lesspipe %s %s"
declare -x LESSOPEN="| /usr/bin/lesspipe %s"
declare -x LOGNAME="root"
declare -x MAIL="/var/mail/root"
declare -x OLDPWD
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
declare -x PWD="/root"
declare -x SHELL="/bin/bash"
declare -x SHLVL="1"
declare -x SSH_TTY="/dev/pts/2"
declare -x TERM="xterm"
declare -x USER="root"
declare -x XDG_DATA_DIRS="/usr/local/share:/usr/share:/var/lib/snapd/desktop"
2.1. 與環境變數相關的命令
有5
個命令都與變數
有關
set
unset
env
declare
export
readonly
set
命令會輸出所有的變數
(全域性變數
和 區域性變數
),直接在shell
中輸入set
,會有很多的資料輸出,建議用set | less
進行檢視,使用set | wc -l
可以發現一共有2106
行資料,而且本身set
命令也有很多選項和玩法,以後在慢慢研究。其中set -o
會顯示bash shell
的所有引數配置資訊。
env
命令只會顯示全域性變數
。
declare
命令會輸出所有的變數
、函式
、整數
和已經匯出的變數
。用declare | wc -l
一查還是2106
行,declare
本身是可以宣告、取消、檢視變數型別的,也有很多玩法。
export
命令,對於檢視shell
賦予程式的環境變數,我是特別喜歡用export -p
進行顯示,非常清爽。
readonly 變數名
,將設定變數為只讀變數
,出於安全的原故,只讀變數是不可以
被復位/取消
的,只有等到shell
登出。
unset
命令可以清除環境變數
,而且set
,env
,export
設定的變數,都可以用它來清除。
# 設定環境變數
[email protected]:~# export MY_BLOG="http://blog.csdn.net/humanking7/"
[email protected]:~# env | grep MY_BLOG
MY_BLOG=http://blog.csdn.net/humanking7/
[email protected]:~# set | grep MY_BLOG
MY_BLOG=http://blog.csdn.net/humanking7/
[email protected]:~# export -p | grep MY_BLOG
declare -x MY_BLOG="http://blog.csdn.net/humanking7/"
[email protected]:~# declare | grep MY_BLOG
MY_BLOG=http://blog.csdn.net/humanking7/
# 將變數設定為只讀
[email protected]:~# readonly MY_BLOG
# 只讀變數無法改變和刪除
[email protected]:~# export MY_BLOG="csdn"
-bash: MY_BLOG: readonly variable
[email protected]:~# unset MY_BLOG
-bash: unset: MY_BLOG: cannot unset: readonly variable
# 設定一個環境變數,然後清除
[email protected]:~# export WEB_SITE=google.com
[email protected]:~# env | grep WEB_SITE
WEB_SITE=google.com
[email protected]:~# unset WEB_SITE
[email protected]:~# env | grep WEB_SITE
[email protected]:~#
2.2. 自定義環境變數
# 方法1
export variableName=value
# 方法2
declare -x variableName=value
上述的兩個方法也是重新賦值的方法,示例如下:
[email protected]:~# export MY_NAME=Q
[email protected]:~# env | grep MY_NAME
MY_NAME=Q
[email protected]:~# declare -x MY_NAME=F
[email protected]:~# env | grep MY_NAME
MY_NAME=F
[email protected]:~# export MY_NAME=A
[email protected]:~# env | grep MY_NAME
MY_NAME=A
2.3. 讓環境變數永久生效
如果希望環境變數
永久生效,則可以將 環境變數
放在使用者環境變數檔案
或全域性環境變數檔案
裡。
讓環境變數永久生效的常用設定檔案
2.3.1. 使用者環境變數配置
家目錄(比如說家目錄是/root/
)下的兩個檔案中寫入環境變數
(隨便一個就可以)
/root/.bashrc
/root/.bash_profile
2.3.2. 全域性環境變數配置
常見的全域性環境變數
的配置檔案如下:
/etc/bashrc # 推薦在此檔案中優先設定
/etc/profile
/etc/profile.d/
2.4. 啟動順序
Shell
的初始化過程
是這樣的:
bash
檢查檔案/etc/profile
(預設的Shell
主環境變數檔案,每個使用者登入都會載入)是否存在,存在
就讀取環境變數,否則跳過;- 當載入完
/etc/profile
檔案後,才會執行/etc/profile.d/
目錄下的指令碼檔案
,這個目錄下的指令碼檔案有很多
; - 之後
bash
檢查家目錄$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
。
2.5. 小結
環境變數
的知識(見參考文獻1 ):
變數名
通常要大寫。- 變數可以在自身的
Shell
及子Shell
中使用。 - 常用
export
來定義環境變數
。 - 執行
env
預設可以顯示所有的環境變數名稱
及對應的值
。 - 輸出時用
“$變數名”
,取消時用“unset變數名”
。 - 書寫
crond
定時任務時要注意,指令碼要用到的環境變數最好先在所執行的Shell
指令碼中重新定義。 - 如果希望
環境變數
永久生效,則可以將其放在使用者環境變數檔案
或全域性環境變數檔案
裡。
3. 普通變數
3.1. 定義
本地變數
在使用者當前Shell生存期的指令碼
中使用。如果在Shell
中啟動另一個程序
或退出
,那麼變數
將會失效。
有3
種定義方法:
# 賦值時不加引號
variableName=value
# 賦值時加單引號
variableName='value'
# 賦值時加雙引號
variableName="value"
變數
的內容可以用單引號
或雙引號
引起來,也可不加引號
,但是這三者的含義是不同的。
3.2. 輸出及其顯示
$變數名
表示輸出變數
,可以用$變數名
和${變數名}
兩種用法。
3.2.1. 例子1
#!/bin/bash
# author:Q
# url:http://blog.csdn.net/humanking7/
var1=2018
var2='2018'
var3="2018"
echo "var1=$var1"
echo "var2=$var2"
echo "var3=${var3}"
執行結果:
[email protected]:~# ./t2.sh
var1=2018
var2=2018
var3=2018
3.2.2. 例子2
#!/bin/bash
# author:Q
# url:http://blog.csdn.net/humanking7/
var1=2018
var1=2018-$var1
var2='2018-$var1'
var3="2018-$var1"
echo "var1=$var1"
echo "var2=$var2"
echo "var3=${var3}"
執行結果:
[email protected]:~# ./t2.sh
var1=2018-2008
var2=2018-$var1
var3=2018-2018-2008
分析:
第1
種定義方式,var1
,是不加任何引號
直接定義變數的內容(值)
。當內容
為 簡單連續的數字
、字串
、路徑名
時,可以這樣用。不加引號時,值
裡有變數
的 會被解析後再輸出,上述變數定義中因為$var1
的值被解析為2018
,因此新的var1
值就是2018-2018
。
第2
種定義方式,通過單引號
定義。這種定義方式的特點就是,單引號裡面是什麼,輸出內容就是什麼,即使內容(值)
裡面有變數
或者命令
(命令需要反引號引起來)。所以對var2
定義是2018-$var1
,最終也是原樣輸出。
第3
種定義方式,通過雙引號
定義。這種定義方式的特點是,輸出變數內容時引號裡的變數及命令會經過解析後再輸出內容。這種方式比較適合於字串
中附帶有變數
及命令
且想將其解析後
再輸出的變數定義。
Tip:
數字內容
的變數定義可以不加引號
;- 其他沒有特別要求的
字串
等定義最好都加上雙引號
; - 如果真的需要
原樣輸出
就加單引號
。
3.3. 把命令的結果作為變數的內容賦值的方法
對需要獲取命令結果的變數內容賦值的常見方法有2種:
# 方法1
# 把命令用反引號引起來,不推薦使用這種方法,因為容易和單引號混淆
variableName=`ls`
# 方法2
# 把命令用$()括起來,推薦使用這種方法
variableName=$(ls)
方法1:
[email protected]:~# ls -1
code
control_vpn
restart_ss.sh
showUsed_ss.sh
t2.sh
[email protected]:~# cmd=`ls -1`
[email protected]:~# printf "$cmd"
code
control_vpn
restart_ss.sh
showUsed_ss.sh
方法2:
[email protected]:~# cmd2=$(ls -1)
[email protected]:~# printf "$cmd2"
code
control_vpn
restart_ss.sh
showUsed_ss.sh
3.4. 注意
單獨拎出來寫一個小節,覺得是這個有點重要。
在變數名
前加$
可以取得該變數的值
,使用echo
或 printf
命令可以顯示變數的值
,$變數名
和${變數名}
的寫法不同,但效果是一樣的。
當變數
後面連線有其他字元的時候,必須給變數加上大括號{}
,如下面的例子:
[email protected]:~# var1='my '
[email protected]:~# var1name=csdn
[email protected]:~# echo $var1name
csdn
[email protected]:~# echo ${var1}name
my name
Tip:
數字內容
的變數定義可以不加引號
;- 其他沒有特別要求的
字串
等定義最好都加上雙引號
; - 如果真的需要
原樣輸出
就加單引號
。 - 希望
變數值引用命令
並獲取命令的結果時就用反引號
或$()
4. 例子
例子1:
[email protected]:~# echo "today : `date`"
today : Thu Nov 29 14:07:43 UTC 2018
[email protected]:~# echo "today : $(date)"
today : Thu Nov 29 14:07:57 UTC 2018
例子2:
# test.txt 檔案裡面有6行內容
# 其中有2行包含變數var1的值"csdn"
# 其中有2行包含"$var1",這個字串
[email protected]:~# cat test.txt
csdn
https://blog.csdn.net/humanking7/
baidu.com
google.com
$var1
$var1name
# 定義一個變數
[email protected]:~# var1=csdn
# 查詢變數"值" 與 檔案匹配的內容
[email protected]:~# grep $var1 test.txt
csdn
https://blog.csdn.net/humanking7/
[email protected]:~# grep ${var1} test.txt
csdn
https://blog.csdn.net/humanking7/
[email protected]:~# grep "$var1" test.txt
csdn
https://blog.csdn.net/humanking7/
# 查詢字串"$var1" 與 檔案匹配的內容
[email protected]:~# grep '$var1' test.txt
$var1
$var1name
5. 參考文獻:
OK!
以上,Enjoy~