跳轉到內容

Bourne Shell 指令碼/變數擴充套件

來自 Wikibooks,開放世界中的開放書籍

環境 模組中,我們介紹了環境變數的概念,作為儲存小片段資料的一種通用方式。在本模組中,我們將深入探討如何使用這些變數:'變數擴充套件'、'引數替換'或簡稱'替換'。

使用變數被稱為替換的原因是,Shell 實際上用每個變數的值替換對任何變數的引用。這在評估命令列時完成,這意味著變數替換是在命令實際執行之前進行的。

使用變數的最簡單方法是我們已經見過的,在變數名前面加上一個 '$'。例如

簡單使用變數

程式碼:

$ USER=JoeSixpack
$ echo $USER

輸出:

JoeSixpack
在執行 echo 命令之前,值 JoeSixpack 被替換為 $USER。

當然,一旦替換完成,結果仍然只是變數中的文字。該文字的解釋仍然由執行的任何程式完成。例如

變數不會創造奇蹟

程式碼:

$ USER=JoeSixpack
$ ls $USER

輸出:

ls: 無法訪問 JoeSixpack: 沒有此檔案或目錄
僅僅因為文字來自變數,並不意味著檔案存在。

基本變數擴充套件已經相當靈活。您可以按照上面描述的方式使用它,但也可以使用變數來建立更長的字串。例如,如果您想將應用程式的日誌目錄設定為主目錄中的 "log" 目錄,您可以這樣填寫設定

$HOME/log

如果您要更頻繁地使用該設定,您可能想要建立自己的變數,例如

LOGDIR=$HOME/log

當然,如果您想要為不同的程式建立特定的日誌子目錄,那麼 Wyxliz 應用程式的日誌將進入目錄

$LOGDIR/Wyxliz/

替換形式

[編輯 | 編輯原始碼]

Bourne Shell 有許多不同的變數替換語法,每種語法都有其自己的含義和用途。在本節中,我們將研究這些語法。

基本變數替換

[編輯 | 編輯原始碼]

我們已經詳細討論過基本變數替換:您定義一個變數,在其前面加上一個 '$',Shell 會用變數的值替換它。到目前為止,您可能已經厭倦了聽到它。

但是我們還沒有談到基本變數替換中您可能會遇到的一個情況。考慮以下情況

向變數的值新增一些文字

程式碼:

$ ANIMAL=duck
$ echo One $ANIMAL, two $ANIMALs

輸出:

一隻鴨子,兩隻
嗯......我們缺少了什麼......

那麼這裡出了什麼問題?好吧,顯然 Shell 沒有為 ANIMAL 變數替換任何東西,但為什麼?因為加上 's' 後,Shell 認為我們要求的是不存在的 ANIMALs 變數。但這怎麼會這樣?我們之前在字串中間使用過變數(如 '/home/ANIMAL/logs')。但是 's' 不是 '/':'s' 可以是變數名的一部分,因此 Shell 無法區分它們。在您必須明確地將變數與其他文字分隔開的情況下,可以使用大括號

向變數的值新增一些文字,第 II 部分

程式碼:

$ ANIMAL=duck
$ echo One $ANIMAL, two ${ANIMAL}s

輸出:

一隻鴨子,兩隻鴨子
好多了!

兩種情況(有括號和沒有括號)都算作基本變數替換,規則完全相同。只需記住不要在大括號和變數名之間留任何空格。

帶有預設值的替換

[編輯 | 編輯原始碼]

由於變數可以為空,您通常會在指令碼中編寫程式碼來檢查強制變數是否真的有值。但在可選變數的情況下,通常不進行檢查,而是使用一個預設值來處理變數未定義的情況。這種情況實際上非常普遍,因此 Bourne Shell 為其定義了一種特殊語法:破折號。由於破折號對 Shell 也有其他含義,因此您必須將其與大括號結合起來 - 最終的結果看起來像這樣

${varname[:]-default}
* 其中 varname 是變數的名稱
default 是在 varname 未定義時使用的值

同樣,不要在大括號和其餘文字之間留任何空格。使用此語法的步驟如下

預設值

程式碼:

$ THIS_ONE_SET=Hello
$ echo $THIS_ONE_SET ${THIS_ONE_NOT:-World}

輸出:

Hello World

將其與以下程式碼進行比較

無需預設值

程式碼:

$ TEXT=aaaaaahhhhhhhh
$ echo Say ${TEXT:-bbbbbbbbbb}

輸出:

說啊......啊......

沒有冒號,變數將僅在未定義時被替換

帶冒號和不帶冒號的預設值
$ 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


帶有預設賦值的替換

[編輯 | 編輯原始碼]

作為預設值的擴充套件,存在一種語法不僅提供預設值,而且同時將預設值賦給未設定的變數。它看起來像這樣

${varname[:]=default}
* 其中 varname 是變數的名稱
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


實際值的替換

[編輯 | 編輯原始碼]

這種替換有點像快速測試來檢視變數是否已定義(通常這就是它的用途)。它有點像預設值語法的反向,看起來像這樣

${varname[:]+substitute}
* 其中 varname 是變數的名稱
substitute 是在 varname 已定義時使用的值

如果變數定義,則此語法將返回替換值。乍一看這似乎違反直覺,尤其是當您問如果變數定義會返回什麼 - 並瞭解到返回值為空時。以下是一個示例

實際值替換
$ echo ${NEWVAR:+newval}

$ NEWVAR=oldval
$ echo ${NEWVAR:+newval}
newval


那麼,這種符號有什麼用呢?好吧,它經常用於必須檢查大量變數是否已設定的指令碼中。在這種情況下,變數具有值意味著已啟用某個選項,因此您感興趣的是知道變數是否具有值,而不是該值是什麼。它看起來有點像這樣(虛擬碼,這在 Shell 中實際不起作用)

預設值賦值
if ${SPECIFIC_OPTION_VAR:+optionset} == optionset then ...


沒有冒號,變數即使為空也會被替換

預設值賦值
$ 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}
* 其中 varname 是變數的名稱
如果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


下一頁: 控制流 | 上一頁: 環境
首頁: Bourne Shell 指令碼
華夏公益教科書