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,
這種最終的語法就像一個除錯檢查,用來檢查變數是否被設定。它看起來像這樣
如果varname沒有定義,則會列印message。
使用這種語法,如果變數已定義,一切正常。否則,將列印訊息,並且命令或指令碼以非零退出狀態退出。或者,如果沒有訊息,則會列印文字“引數為空或未設定”。
您可以使用這種語法來檢查指令碼的必需變數是否已設定,並在未設定時列印錯誤訊息。
$ 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