Bourne Shell 指令碼/變數擴充套件
在 環境 模組中,我們介紹了環境變數的概念,它是一種通用的方法來儲存小塊資料。在本模組中,我們將深入探討使用這些變數:'變數擴充套件'、'引數替換'或簡稱為 '替換'。
使用變數被稱為替換的原因是,shell 會將對任何變數的引用替換為它的值。這在評估命令列時完成,這意味著變數替換髮生在命令實際執行之前。
使用變數的最簡單方法是我們已經見過的,在變數名前面加一個 '$'。例如
當然,一旦替換完成,結果仍然只是變數中的文字。對該文字的解釋仍然由執行的程式完成。例如
基本變數擴充套件已經非常靈活。你可以像上面描述的那樣使用它,但也可以使用變數來建立更長的字串。例如,如果你想將應用程式的日誌目錄設定為你主目錄中的 "log" 目錄,你可以這樣填寫設定
$HOME/log
如果你要更頻繁地使用該設定,你可能想建立你自己的變數,例如
LOGDIR=$HOME/log
當然,如果你想為不同的程式建立特定的日誌子目錄,那麼 Wyxliz 應用程式的日誌將位於目錄
$LOGDIR/Wyxliz/
Bourne Shell 有許多不同的變數替換語法,每種語法都有其含義和用途。在本節中,我們將研究這些語法。
我們已經詳細討論了基本變數替換:你定義一個變數,在它前面加上一個 '$',shell 將用變數的值替換該變數。現在你可能已經厭倦了聽到它。
但我們還沒有討論基本變數替換中你可能會遇到的一個情況。考慮以下情況
那麼哪裡出錯了呢?顯然,shell 沒有為 ANIMAL 變數替換任何東西,但為什麼呢?因為加上 's' 後,shell 認為我們正在請求不存在的 ANIMALs 變數。但這究竟是怎麼回事呢?我們之前已經在字串中間使用過變數(例如 '/home/ANIMAL/logs')。但 's' 不是 '/':'s' 可以是變數名稱的有效部分,因此 shell 無法區分它們。在必須明確將變數與其他文字分隔開的情況下,可以使用大括號
兩種情況(帶括號和不帶括號)都屬於基本變數替換,規則完全相同。只需記住不要在括號和變數名稱之間留任何空格。
由於變數可以為空,因此你經常會在指令碼中編寫程式碼來檢查強制性變數是否確實具有值。但在可選變數的情況下,通常更方便的是不檢查,而是使用預設值來代替未定義的變數。這種情況實際上非常普遍,以至於 Bourne Shell 為此定義了一種特殊的語法:連字元。由於連字元對 shell 也有其他含義,因此你必須將其與大括號結合使用 - 最終結果如下
而 default 是在 varname 未定義時使用的值
同樣,不要在括號和其他文字之間留任何空格。使用這種語法的示例如下
與之對比
沒有冒號,變數只有在未定義時才會被替換
$ VAR=value EMPTY_VAR=
$ echo ${VAR:-empty}, ${EMPTY_VAR:-empty}, ${ABSENCE_VAR:-empty}
value, empty, empty
$ echo ${VAR-empty}, ${EMPTY_VAR-empty}, ${ABSENCE_VAR-empty}
value, , empty
作為預設值的擴充套件,有一種語法不僅提供了預設值,而且同時將預設值賦予未設定的變數。它看起來像這樣
而 default 是在 varname 未定義時使用的並被賦值的值
像往常一樣,避免在括號之間留空格。以下示例演示了這種語法的工作方式
$ echo $NEWVAR
$ echo ${NEWVAR:=newval}
newval
$ echo $NEWVAR
newval
沒有冒號,變數只有在未定義時才會被賦值
$ echo $NEWVAR
$ EMPTY_VAR=
$ unset ABSENCE_VAR
$ echo ${EMPTY_VAR:=empty}, ${ABSENCE_VAR:=empty}
empty, empty
$ echo ${EMPTY_VAR}, ${ABSENCE_VAR}
empty, empty
$ EMPTY_VAR=
$ unset ABSENCE_VAR
$ echo ${EMPTY_VAR=empty}, ${ABSENCE_VAR=empty}
, empty
$ echo ${EMPTY_VAR}, ${ABSENCE_VAR}
, empty
這種替換是一種快速測試,用於檢查變數是否已定義(這通常是它的用途)。它有點類似於預設值語法的反向操作,看起來像這樣
而 substitute 是在 varname 定義時使用的值
如果變數已定義,則此語法返回替換值。這乍一看似乎有悖常理,特別是如果你問如果變數未定義會返回什麼 - 並瞭解到返回的值為空。以下是一個示例
$ echo ${NEWVAR:+newval}
$ NEWVAR=oldval
$ echo ${NEWVAR:+newval}
newval
那麼,這種表示法有什麼用呢?它經常用在必須檢查許多變數是否已設定的指令碼中。在這種情況下,變數具有值意味著已啟用某個選項,因此你感興趣的是知道變數有值,而不是該值是什麼。它看起來像這樣(虛擬碼,這在 shell 中實際上不起作用)
沒有冒號,變數即使為空也會被替換
$ VAR=value EMPTY_VAR=
$ echo ${VAR:+newvalue}, ${EMPTY_VAR:+newvalue}, ${ABSENCE_VAR:+newvalue}
newvalue, ,
$ echo ${VAR+newvalue}, ${EMPTY_VAR+newvalue}, ${ABSENCE_VAR+newvalue}
newvalue, newvalue,
最後一種語法是一種除錯檢查,用於檢查變數是否已設定。它看起來像這樣
而 message 是在 varname 未定義時列印的內容
使用此語法,如果變數已定義,則一切正常。否則,將列印訊息,並且命令或指令碼將以非零退出狀態退出。或者,如果沒有訊息,將列印文字 "引數為空或未設定"。
你可以使用此語法來檢查指令碼的強制性變數是否已設定,並在它們未設定時列印錯誤訊息。
$ echo ${SOMEVAR:?has not been set}
-sh: SOMEVAR: has not been set
$ echo ${SOMEVAR:?}
-sh: SOMEVAR: parameter null or not set
帶冒號,變數也會被檢查是否為空
$ EMPTY_VAR=
$ echo ${EMPTY_VAR:?has not been set or empty}
-sh: EMPTY_VAR: has not been set or empty
$ echo ${ABSENCE_VAR:?has not been set or empty}
-sh: ABSENCE_VAR: has not been set or empty
$ echo ${EMPTY_VAR?has not been set or empty}
$ echo ${ABSENCE_VAR?has not been set or empty}
-sh: ABSENCE_VAR: has not been set or empty