Shell 變量
1. Shell 變量概述
變量是任何程序或腳本的重要組成部分,變量為程序或腳本訪問內(nèi)存中的可修改的一塊數(shù)據(jù)提供了簡(jiǎn)單的方式。
Linux Shell 中的變量可以被指定為任意的數(shù)據(jù)類型,比如文本字符串或者數(shù)值。你也可以通過修改 Shell 中的變量來改變 Shell 的樣式。
接下來就讓我們來了解和學(xué)習(xí)一下 Shell 中的變量吧。
1.1 Shell 變量是什么
Shell 變量是什么呢,顧名思義,就是可以變化的量,如果有編程基礎(chǔ)的讀者知道任何程序中都有變量,從我們小時(shí)候做數(shù)學(xué)題,定義的 x 變量,最終給定值,用值替換 x 變量,這就是我們最初接觸的變量,它和我們?cè)?Shell 中接觸的變量本質(zhì)上是一致的。
變量在 Shell 中是存儲(chǔ)計(jì)算器內(nèi)存的單元,其中存放的值可以改變,當(dāng)我們?cè)诰帉?Shell 腳本中,如果一些經(jīng)常用的字符串或數(shù)字我們就可以定義一個(gè)變量,將具體的值賦給這個(gè)變量,然后在具體的函數(shù)或腳本中引用這個(gè)變量,就相當(dāng)于拿到了這個(gè)值。
1.2 為什么要用變量
我們大概了解了 Shell 變量是什么,那么為什么在 Shell 腳本中需要變量呢?
例如在一個(gè) Shell 腳本中,我們需要指定一個(gè)目錄,腳本內(nèi)多處調(diào)用了這個(gè)目錄名稱,現(xiàn)在我們有個(gè)需求目錄名稱改變了,我們?cè)撛趺崔k呢,在腳本中每個(gè)使用該目錄的地方都需要改成新的目錄名稱,有沒有簡(jiǎn)單的方法只需要改一處地方呢,這時(shí)候就用到了我們的變量,在腳本的全局定義一個(gè)變量例如 BASE_DIR
,然后將目錄賦值給這個(gè)變量,在具體引用的時(shí)候利用這個(gè)目錄的變量名稱,下次需要我們改,只用改最前面這個(gè)變量即可。
因此我們使用變量就是為了方便,同時(shí)也使得我們的腳本更具靈活性擴(kuò)展性與后期的可維護(hù)性。
2. Shell 變量基本操作
我們知道了 Shell 中變量是什么以及其在 Shell 編寫中的重要性,那么讓我們先來學(xué)習(xí) Shell 變量的基本操作。
2.1 變量的定義
在使用 Shell 變量前,需要先定義變量,定義變量的方式有三種:
2.1.1 直接賦值
顧名思義就是直接將一個(gè)值賦值給一個(gè)變量名稱,這種需要注意值中不能包含空白字符
例如:正確的直接賦值變量:DIR=/tmp
,其中 DIR
為變量名,/tmp
為值
錯(cuò)誤的直接賦值:STRING=hello Shell
,其中 STRINNG
為變量名,hello Shell
為值,其中值包含了空白字符,這種賦值變量就是錯(cuò)誤的。
2.1.2 單引號(hào)賦值
如果值中為普通字符,那么單引號(hào)賦值與雙引號(hào)賦值沒有區(qū)別,其可以包含空白字符,但是如果其中包含了變量的使用,那么單引號(hào)賦值方式為單引號(hào)里面的內(nèi)容是什么就輸出什么,此種賦值方式適用于不希望解析變量的場(chǎng)景,僅顯示純字符串。
例如:
[root@master ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@master ~]# DIR='$PATH'
[root@master ~]# echo $DIR
$PATH
[root@master ~]# DATE='$(date)'
[root@master ~]# echo $DATE
$(date)
PATH
為 linux 系統(tǒng)內(nèi)置的一個(gè)環(huán)境變量,DIR 為我們定義的變量,值為單引號(hào)引起來的 $PATH
,查看其內(nèi)容也為 $PATH
,同理對(duì)于執(zhí)行 date
命令。
2.1.3 雙引號(hào)賦值
與單引號(hào)賦值一樣,其也可以包含空白字符,但是與單引號(hào)賦值不同的是,雙引號(hào)賦值可以解析引號(hào)內(nèi)的變量或執(zhí)行命令,即不是將雙引號(hào)中的變量名和命令原樣輸出,而是解析其中變量的內(nèi)容,然后進(jìn)行輸出。
例如:
[root@master ~]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@master ~]# DIR="$PATH"
[root@master ~]# echo $DIR
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
[root@master ~]# DATE="$(date)"
[root@master ~]# echo $DATE
Sun Mar 8 22:13:57 CST 2020
可以通過與單引號(hào)示例對(duì)照查看,雙引號(hào)賦值解析了 PATH
變量的值然后輸出,同理對(duì)于執(zhí)行命令 date
。
2.2 變量的使用
我們知道了變量的定義方式,那么該如何使用變量呢?使用變量非常簡(jiǎn)單,只需要在定義的變量名前面添加 $
即可使用定義的變量
例如:
[root@master ~]# DIR=/tmp
[root@master ~]# echo $DIR
/tmp
在使用變量中有一種特殊情況,需要我們手動(dòng)指定變量的邊界是什么,此時(shí)就需要使用到 {}
。
[root@master ~]# STRING="hello Shell"
[root@master ~]# echo "test $STRINGtest"
test
[root@master ~]# echo "test ${STRING}test"
test hello Shelltest
通過示例我們能夠看出,不使用 {}
引起來變量,如果變量名后面繼續(xù)有字符,Shell 無法判斷我們的變量邊界在哪里,我們推薦在使用變量的時(shí)候都帶上 {}
減少出錯(cuò)的概率,并且方便我們?nèi)藶樽R(shí)別變量的邊界。
2.3 變量的更新
我們已經(jīng)定義了變量,如果對(duì)變量進(jìn)行更新修改呢,更新修改變量重新賦值即可
例如:
[root@master ~]# DIR=/tmp
[root@master ~]# echo $DIR
/tmp
[root@master ~]# DIR=/root
[root@master ~]# echo $DIR
/root
另外在變量中存在只讀變量,顧名思義其為定義好后,只能只讀,不能對(duì)其進(jìn)行修改,使用 readonly 命令可以將變量定義為只讀變量
[root@master ~]# readonly STRING="Shell"
[root@master ~]# echo ${STRING}
Shell
[root@master ~]# STRING="test"
-bash: STRING: readonly variable
[root@master ~]# echo ${STRING}
Shell
可以看到我們使用 readonly 定義變量后,對(duì)變量進(jìn)行修改時(shí)候報(bào)錯(cuò),只讀變量無法進(jìn)行修改。
2.4 變量的刪除
變量的刪除使用 unset,刪除后就消除了定義的變量,變量被刪除后不能再次使用;unset 命令不能刪除只讀變量。
例如
[root@master ~]# DIR=/tmp
[root@master ~]# echo "dir is ${DIR}"
dir is /tmp
[root@master ~]# unset DIR
[root@master ~]# echo "dir is ${DIR}"
dir is
3. Shell 變量規(guī)范
與其他語言一樣,Shell 中變量也需要遵循一定的規(guī)范,
3.1 命名規(guī)范
- 變量命名只能使用英文字母,數(shù)字和下劃線,首字母不能以數(shù)字開頭
- 例如
- 正常變量:
BASE_DIR
,File_Name
,AEG3
,_DIR
等都是正常的變量 - 無效變量:
1file
,#dir
- 正常變量:
- 例如
- 變量名中間不能使用空格或標(biāo)點(diǎn)符號(hào)
- 例如:
DIR FILE
,DIR?FILE
就為無效變量
- 例如:
- 變量命名不能使用 base 里面的關(guān)鍵字(help 來查看關(guān)鍵字)
- Shell 變量大小寫敏感,也就是定義為大寫的變量名,引用的時(shí)候必須完全一致。
- 例如:
DIRNAME
和dirname
就是兩個(gè)不同的變量
- 例如:
3.2 賦值規(guī)范
-
變量與值直接使用 “=” 連接,等號(hào)兩邊不能存在空白字符;
- 例如:
dirname = "/tmp"
賦值方法就是錯(cuò)誤的。
- 例如:
-
如果值中有空白字符,使用單引號(hào)或雙引號(hào)引起來,雙引號(hào)對(duì)于其中引用的值將會(huì)根據(jù)其內(nèi)容轉(zhuǎn)化,單引號(hào)內(nèi)的特殊字符則一律當(dāng)字符串進(jìn)行處理;
- 例如:
DIRNAME="$PATH"
的值為系統(tǒng) PATH 實(shí)際的可執(zhí)行文件路徑,DIRNAME='$PATH'
的值為 $PATH 的字符串。
- 例如:
-
可用
\
來轉(zhuǎn)譯變量,讓其變?yōu)橐话阕址?/p>- 例如:
DIRNAME=\$PATH
的值為 $PATH 的字符串。
- 例如:
-
如果變量的值為指令,可用使用反撇號(hào),或 $() 來引用;
- 例如:下面兩個(gè)是一樣的
-
DATE=`date` DATE=$(date)
-
在腳本中定義普通字符串變量時(shí),應(yīng)盡量把變量的內(nèi)容用雙引號(hào)括起來;
- 例如:
DIRNAME="/tmp"
- 例如:
-
單純數(shù)字的變量?jī)?nèi)容可以不加引號(hào);
- 例如:
NUM=10
- 例如:
4. 變量的分類
Shell 的變量有三種分類,每種都有其不同的作用范圍
4.1 局部變量
局部變量,顧名思義其只在 Shell 腳本中定義的變量,或在 Shell 腳本函數(shù)中定義的變量,只能在 Shell 腳本中使用,或只能在 Shell 腳本函數(shù)中使用
例如:
[root@master Shell]# cat local_var.sh
#!/bin/bash
DIR=/tmp
echo "dir is ${DIR}"
[root@master Shell]# bash local_var.sh
dir is /tmp
[root@master Shell]# echo "dir is ${DIR}"
dir is
我們可以看出在腳本內(nèi)部定義的變量 DIR
只在 local_var
腳本內(nèi)可以使用,在全局下沒有此變量,后期我們學(xué)到函數(shù)再來說明函數(shù)中的局部變量。
4.2 環(huán)境變量
環(huán)境變量為當(dāng)前 Shell 中定義的臨時(shí)變量,在當(dāng)前 Shell 定義的變量可以傳遞給子 Shell,沒有父子關(guān)系的 Shell 不能使用此變量,當(dāng)然可以利用 export
將當(dāng)前 Shell 的變量傳遞給其他終端的 Shell 中。
當(dāng)前 Shell 為父 Shell,在其上運(yùn)行 bash
就可以進(jìn)入到子 Shell 中,讓我們來看示例
# 在當(dāng)前Shell中定義變量STR
[root@master Shell]# STR="Shell"
[root@master Shell]# echo "hello ${STR}"
hello Shell
# 運(yùn)行命令bash進(jìn)入子Shell
[root@master Shell]# bash
# 在子Shell中查看沒有STR
[root@master Shell]# echo "hello ${STR}"
hello
# 退出子Shell回到父Shell
[root@master Shell]# exit
exit
# 利用export導(dǎo)入環(huán)境變量
[root@master Shell]# export STR="Shell"
# 在此進(jìn)入子Shell
[root@master Shell]# bash
# 查看子Shell中已經(jīng)有了變量STR
[root@master Shell]# echo "hello ${STR}"
hello Shell
環(huán)境變量為臨時(shí)的,在我們啟動(dòng)終端的時(shí)候,系統(tǒng)會(huì)從特定的文件中加載一系列環(huán)境變量。
系統(tǒng)中還有一些系統(tǒng)內(nèi)置的變量,例如 PATH
,USER
等,我們可以利用命令 env 或 export 來查看當(dāng)前 Shell 的環(huán)境變量,例如:
[root@master Shell]# env
XDG_SESSION_ID=1276
HOSTNAME=master
SELINUX_ROLE_REQUESTED=
Shell=/bin/bash
TERM=xterm
HISTSIZE=1000
SSH_CLIENT=61.150.11.174 55929 22
SELINUX_USE_CURRENT_RANGE=
SSH_TTY=/dev/pts/0
USER=root
...
# 查看當(dāng)前Shell
[root@master Shell]# echo $Shell
/bin/bash
# 查看可執(zhí)行命令的路徑
[root@master Shell]# echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
# 查看當(dāng)前登錄系統(tǒng)用戶
[root@master Shell]# echo $USER
root
linux 系統(tǒng)的一些內(nèi)置參數(shù)
$Shell 默認(rèn) Shel
$HOME 當(dāng)前用戶家目錄
$IFS 內(nèi)部字段分隔符
$LANG 默認(rèn)語
$PATH 默認(rèn)可執(zhí)行程序路徑
$PWD 當(dāng)前目錄
$UID 當(dāng)前用戶 ID
$USER 當(dāng)前用戶
$HISTSIZE 歷史命令大小,可通過 HISTTIMEFORMAT 變量設(shè)置命令執(zhí)行時(shí)間
$RANDOM 隨機(jī)生成一個(gè) 0 至 32767 的整數(shù)
$HOSTNAME 主機(jī)名
4.3 全局變量
全局變量為在當(dāng)前 Shell 進(jìn)程中運(yùn)行的腳本都可以使用該變量,在 Shell 中默認(rèn)定義的變量就是全局變量,例如:
[root@master Shell]# cat global_var1.sh
#!/bin/bash
echo "${STR1}" # 查看STR1變量的內(nèi)容
STR2="sh" # 定義STR2變量的值為sh
[root@master Shell]# cat global_var2.sh
#!/bin/bash
echo "${STR2}" # 查看STR2變量的內(nèi)容
[root@master Shell]# STR1="Shell"
[root@master Shell]# . ./global_var1.sh
Shell
[root@master Shell]# . ./global_var2.sh
sh
我們可以看出利用.
來運(yùn)行 Shell 腳本,是在當(dāng)前用戶登錄的 Shell 終端中運(yùn)行,其變量是在當(dāng)前 Shell 進(jìn)程中可以共享的。
5. 實(shí)例
我們通過簡(jiǎn)單編寫一個(gè)獲取當(dāng)前用戶登錄信息的腳本,來展示目前登錄用戶的信息
[root@master Shell_var]# cat login_info.sh
#!/bin/bash
# Description: login info scripts
# Auth: kaliarch
# Email: kaliarch@163.com
# function: show user info
# Date: 2020-03-08 13:36
# Version: 1.0
echo "當(dāng)前登錄系統(tǒng)用為: ${USER}"
echo "當(dāng)前登錄系統(tǒng)時(shí)間: $(date +"%Y-%m-%d %H:%M:%S")"
echo "當(dāng)前登錄系統(tǒng)Shell: ${Shell}"
echo "當(dāng)前用戶家目錄為: ${HOME}"
# 運(yùn)行腳本查看內(nèi)容
[root@master Shell_var]# bash login_info.sh
當(dāng)前登錄系統(tǒng)用為: root
當(dāng)前登錄系統(tǒng)時(shí)間: 2020-03-08 12:16:04
當(dāng)前登錄系統(tǒng)Shell: /bin/bash
當(dāng)前用戶家目錄為: /root
6. 注意事項(xiàng)
- 在引用變量是我們遵守規(guī)范,帶上
{}
,可以避免不必要的麻煩和坑; - 命名變量見名知意,形成有自己一套的命名規(guī)范;
- 學(xué)習(xí) Shell 需要多動(dòng)手實(shí)踐,將變量的三種類型通過實(shí)踐真正理解,后期在編寫 Shell 的時(shí)候可以靈活運(yùn)用。
7. 小結(jié)
變量在我們 Shell 編程中的有這獨(dú)特的地位,其將我們的一些數(shù)據(jù)通過一次性的賦值,大大增強(qiáng)了腳本的靈活性與后期可維護(hù)性。我們需要通過本章節(jié)充分理解 Shell 的基本操作及其種類,在編寫 Shell 中靈活運(yùn)用,遵循定義及使用規(guī)范,可以使得我們編寫的 Shell 更加友好及健壯。