鳥哥的Linux私房菜讀書筆記--shell的變數功能
1、變數的特性
變數的可變性和方便性、影響bash環境操作的變數、指令碼程式的設計。一般情況下系統內定變數為大寫。
2、變數的取用與設定
<1>變數的取用
命令:$ echo $變數名
命令:$ echo $ { 變數名 }
<2>變數的設定(變數命名失敗後需要按下復原鍵:ctrl+v)
變數的設定規則 (1) 變數與變數內容以一個等號『=』來連結,如下所示:『myname=VBird』 (2)等號兩邊不能直接接空格符,如下所示為錯誤:『myname = VBird』或『myname=VBird Tsai』 (3)變數名稱只能是英文字母與數字,但是開頭字元不能是數字,如下為錯誤:『2myname=VBird』 (4)變數內容若有空格符可使用雙引號『"』(成對)或單引號『'』(成對)將變數內容結合起來,但 o 雙引號內的特殊字元如 $ 等,可以保有原本的特性
在當前shell下去啟用新的shell,新啟用的即為其子程式,一般情況下父程式定義的變數在子程式中是無法使用的,可以通過export命令將變數變成環境變數,就能夠在子程式下使用了。
3、環境變數的功能
<1>用env觀察環境變數與常見你環境變數說明
命令:$ env ##列出當前shell環境下 的所有環境變數與其內容
變數:HOME 使用cd ~可以切換到自己的家目錄下,其實質是採用變數~來代替家目錄的路徑
變數:SHELL 檢視當前環境使用的shell是哪種
變數:HISTSIZE 檢視歷史指令
變數:MAIL 當使用mail指令收信時,系統會讀取郵箱信件
變數:PATH 執行檔案搜尋路徑,目錄間用:隔開
變數:LANG 檢視語系資料
變數:RANDOM 檢視由隨機數生成器生成的隨機數
<2>用set觀察所有變數(含環境變數與自定義變數)
命令:$ set
變數:PS1 提示字元的設定
§ \d :可顯示出『星期 月 日』的日期格式,如:"Mon Feb 2" § \H :完整的主機名。舉例來說,鳥哥的練習機為『study.centos.vbird』 § \h :僅取主機名在第一個小數點之前的名字,如鳥哥主機則為『study』後面省略 § \t :顯示時間,為 24 小時格式的『HH:MM:SS』 § \T :顯示時間,為 12 小時格式的『HH:MM:SS』 § \A :顯示時間,為 24 小時格式的『HH:MM』 § \@ :顯示時間,為 12 小時格式的『am/pm』樣式 § \u :目前使用者的賬號名稱,如『dmtsai』; § \v :BASH 的版本資訊,如鳥哥的測試主機版本為 4.2.46(1)-release,僅取『4.2』顯示 § \w :完整的工作目錄名稱,由根目錄寫起的目錄名稱。但家目錄會以 ~ 取代; § \W :利用 basename 函式取得工作目錄名稱,所以僅會列出最後一個目錄名。 § \# :下達的第幾個指令。 § \$ :提示字元,如果是 root 時,提示字元為 # ,否則就是 $ 囉~
變數:$ 關於本機的shell的PID,即執行緒代號(process ID)
變數:? 關於上一個指令的回傳值。執行某些指令時,這些指令都會回傳一個執行後的程式碼,如果成功執行指令,則回傳 值為0,如果錯誤就會回傳錯誤程式碼
變數:OSTYPE,HOSTTYPE,MACHTYPE 主機硬體與核心的等級
<3>自定義變數轉化為環境變數
命令:$ export 變數名稱 ##在當前shell下去啟用新的shell,新啟用的即為其子程式,一般情況下父程式定義的變數在子 程式中是無法使用的,可以通過export命令將變數變成環境變數,就能夠在子程式下使用了。
4、影響顯示結果的語系變數
命令:$ locale ##檢視支援語系
當系統設定LANG或者LC_ALL時,其它的語系變數將被這兩個取代
主機內的語系檔案放置位置:/usr/lib/locale
整體系統預設語系定義位置:/etc/locale.conf
5、變數的有效範圍
環境變數=全域性變數 自定義變數=區域性變數
環境變數之所以可以被子程式引用是因為記憶體配置關係:
· 當啟動一個 shell,作業系統會分配一記憶區塊給 shell 使用,此記憶體內之變數可讓子程式取用 · 若在父程式利用 export 功能,可以讓自定義變數的內容寫到上述的記憶區塊當中(環境變數); · 當載入另一個 shell 時 (亦即啟動子程式,而離開原本的父程式了),子 shell 可以將父 shell 的環境變數所 在的記憶區塊匯入自己的環境變數區塊當中。
6、變數鍵盤讀取、陣列與宣告
<1>讀取
命令:$ read [-pt] 變數名 選項與引數: -p :後面可以接提示字元! -t :後面可以接等待的『秒數!』
<2>宣告變數的型別(declare / typeset)
命令:$ declare [-aixr] variable 選項與引數: -a :將後面名為 variable 的變數定義成為陣列 (array) 型別 -i :將後面名為 variable 的變數定義成為整數數字 (integer) 型別 -x :用法與 export 一樣,就是將後面的 variable 變成環境變數;將-變成+,可以使環境變數轉換為自定義變數。 -r :將變數設定成為 readonly 型別,該變數不可被更改內容,也不能 unset 範例一:讓變數 sum 進行 100+300+50 的加總結果 [[email protected] ~]$ sum=100+300+50 [[email protected] ~]$ echo ${sum} 100+300+50 <==咦!怎麼沒有幫我計算加總?因為這是文字型態的變數屬性啊! [[email protected] ~]$ declare -i sum=100+300+50 [email protected] ~]$ echo ${sum} 450 由於在預設的情況底下, bash 對於變數有幾個基本的定義: · 變數型別預設為『字串』,所以若不指定變數型別,則 1+2 為一個『字串』而不是『計算式』。 所以 上述第一個執行的結果才會出現那個情況的; · bash 環境中的數值運算,預設最多僅能到達整數形態,所以 1/3 結果是 0;
<3>陣列變數型別
命令:陣列名[序號]=內容
讀取陣列變數時,建議直接以:$ echo { 陣列名[序號] }來讀取。
7、與檔案系統及程式的限制關係:ulimit
限制使用者的某些系統資源
命令:$ ulimit [-SHacdfltu] [配額] 選項與引數: -H :hard limit ,嚴格的設定,必定不能超過這個設定的數值; -S :soft limit ,警告的設定,可以超過這個設定值,但是若超過則有警告訊息。 在設定上,通常 soft 會 比 hard 小,舉例來說,soft 可設定為 80 而 hard設定為 100,那麼你可以使用到 90 (因為沒有超過 100),但 介於 80~100 之間時,系統會有警告訊息通知你! -a :後面不接任何選項與引數,可列出所有的限制額度; -c :當某些程式發生錯誤時,系統可能會將該程式在記憶體中的資訊寫成檔案(除錯用), 這種檔案就被稱為核心檔案 (core file)。此為限制每個核心檔案的最大容量。 -f :此 shell 可以建立的最大檔案容量(一般可能設定為 2GB)單位為 Kbytes,一般使用者只可減少不可增加。 -d :程式可使用的最大斷裂記憶體(segment)容量; -l :可用於鎖定 (lock) 的記憶體量 -t :可使用的最大 CPU 時間 (單位為秒) -u :單一使用者可以使用的最大程式(process)數量。
當想要復原ulimit的設定最簡單的辦法是登出重新登入。亦或者可以重新設定ulimit。
8、變數內容的刪除、取代與替換
<1>變數內容的刪除與取代
#:符合取代蚊子最短的那個。 ##:符合取代文字最長的那個。
範例一:先讓小寫的 path 自定義變數設定的與 PATH 內容相同
[[email protected] ~]$ path=${PATH}
[[email protected] ~]$ echo ${path}
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
範例二:假設我不喜歡 local/bin,所以要將前 1 個目錄刪除掉,如何顯示?
[[email protected] ~]$ echo ${path#/*local/bin:}
/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin${variable#/*local/bin:}:上面的特殊字型部分是關鍵詞!用在這種刪除模式所必須存在的
${variable#/*local/bin:}:這就是原本的變數名稱,以上面範例二來說,這裡就填寫 path 這個『變數名稱』啦!
${variable#/*local/bin:}: 這是重點!代表『從變數內容的最前面開始向右刪除』,且僅刪除最短的那個
${variable#/*local/bin:}: 代表要被刪除的部分,由於 # 代表由前面開始刪除,所以這裡便由開始的 / 寫起。
需要注意的是,我們還可以透過萬用字元 * 來取代 0 到無窮多個任意字元
以上面範例二的結果來看, path 這個變數被刪除的內容如下所示:
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
範例三:我想要刪除前面所有的目錄,僅保留最後一個目錄
[[email protected] ~]$ echo ${path#/*:}
/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
# 由於一個 # 僅刪除掉最短的那個,因此他刪除的情況可以用底下的刪除線來看:# /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
[[email protected] ~]$ echo ${path##/*:}
/home/dmtsai/bin
多加了一個 # 變成 ## 之後,他變成『刪除掉最長的那個資料』!亦即是:# /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
範例四:我想要刪除最後面那個目錄,亦即從 : 到 bin 為止的字串
[[email protected] ~]$ echo ${path%:*bin}
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin
# 注意啊!最後面一個目錄不見去!
# 這個 % 符號代表由最後面開始向前刪除!所以上面得到的結果其實是來自如下:
# /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
範例五:那如果我只想要保留第一個目錄呢?
[[email protected] ~]$ echo ${path%%:*bin}
/usr/local/bin
# 同樣的, %% 代表的則是最長的符合字串,所以結果其實是來自如下:
# /usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin
例題:
假設你是 dmtsai ,那你的 MAIL 變數應該是 /var/spool/mail/dmtsai 。假設你只想要保留最後面那個檔名
(dmtsai), 前面的目錄名稱都不要了,如何利用 $MAIL 變數來達成?
答:題意其實是這樣『/var/spool/mail/dmtsai』,亦即刪除掉兩條斜線間的所有資料(最長符合)。 這個時候你就可
以這樣做即可:
[[email protected] ~]$ echo ${MAIL##/*/}
相反的,如果你只想要拿掉檔名,保留目錄的名稱,亦即是『/var/spool/mail/dmtsai』 (最短符合)。但假設
你並不知道結尾的字母為何,此時你可以利用萬用字元來處理即可,如下所示:
[[email protected] ~]$ echo ${MAIL%/*}
範例六:將 path 的變數內容內的 sbin 取代成大寫 SBIN: [[email protected] ~]$ echo ${path/sbin/SBIN} usr/local/bin:/usr/bin:/usr/local/SBIN:/usr/sbin:/home/dmtsai/.local/bin:/home/dmtsai/bin # 這個部分就容易理解的多了!關鍵詞在於那兩個斜線,兩斜線中間的是舊字串 # 後面的是新字串,所以結果就會出現如上述的特殊字型部分囉! [[email protected] ~]$ echo ${path//sbin/SBIN} /usr/local/bin:/usr/bin:/usr/local/SBIN:/usr/SBIN:/home/dmtsai/.local/bin:/home/dmtsai/bin # 如果是兩條斜線,那麼就變成所有符合的內容都會被取代喔!
總結
變數設定方式 | 說明 |
---|---|
${變數#關鍵詞} ${變數##關鍵詞} | 若變數內容從頭開始的資料符合『關鍵詞』,則將符合的最短資料刪除 若變數內容從頭開始的資料符合『關鍵詞』,則將符合的最長資料刪除 |
${變數%關鍵詞} ${變數%%關鍵詞} | 若變數內容從尾向前的資料符合『關鍵詞』,則將符合的最短資料刪除 若變數內容從尾向前的資料符合『關鍵詞』,則將符合的最長資料刪除 |
${變數/舊字串/新字串} ${變數//舊字串/新字串} | 若變數內容符合『舊字串』則『第一個舊字串會被新字串取代』 若變數內容符合『舊字串』則『全部的舊字串會被新字串取代』 |
<2>變數的測試與內容替換(var和str為兩個變數)
變數設定方式 | str 沒有設定 | str 為空字串 | str 已設定非為空字串 |
---|---|---|---|
var=${str-expr} | var=expr | var= | var=$str |
var=${str:-expr} | var=expr | var=expr | var=$str |
var=${str+expr} | var= | var=expr | var=expr |
var=${str:+expr} | var= | var= | var=expr |
var=${str=expr} | str=expr var=expr | str=expr var= | str不變 var=$str |
var=${str:=expr} | str=expr var=expr | str=expr var=expr | str 不變 var=$str |
var=${str?expr} | expr 輸出至 stderr | var= | var=$str |
var=${str:?expr} | expr 輸出至 stderr | expr 輸出至 stderr | var=$str |
總結:(1) - 不會影響舊變數的內容
(2):被測試的變數未被設定或者是已被設定為空字串時,都能夠用後面的內容替代。
(3)(str:)表示沒有設定或為空的字串
(4)= 用來替換新變數的內容