跳轉到內容

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 無法區分它們。在必須明確將變數與其他文字分隔開的情況下,可以使用大括號

將一些文字新增到變數的值,再來一次

程式碼:

$ 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}

輸出:

你好,世界

與之對比

不需要預設值

程式碼:

$ 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 是變數的名稱
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


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