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