本系列文章介紹在 Linux Bash shell 中使用函數的一些執行個體,包括下面的内容:
- 定義函數的格式
- 從函數中傳回内容
- 使用函數名作為函數指針
- 函數内執行cd指令的影響
- 聲明函數内的變量為局部變量
- 擷取傳入函數的所有參數
聲明函數内的變量為局部變量
在 bash 中,沒有使用 local 指令來聲明的變量都是全局變量,在函數内部定義的變量也是全局變量。如果沒有注意到這一點,在函數内操作變量可能會影響到的外部同名變量,造成不預期的結果。
為了避免對外部同名變量造成影響,函數内的變量最好聲明為局部變量,使用 local 指令來聲明。檢視 man bash 裡面對 local 指令的說明如下:
local [option] [name[=value] ...]
For each argument, a local variable named name is created, and assigned value. The option can be any of the options accepted by declare.
When local is used within a function, it causes the variable name to have a visible scope restricted to that function and its children. With no operands, local writes a list of local variables to the standard output.
It is an error to use local when not within a function.
The return status is 0 unless local is used outside a function, an invalid name is supplied, or name is a readonly variable.
即,在函數内,使用 local 指令聲明的變量是局部變量,這些變量在函數外不可見。在函數外,不能使用 local 指令聲明變量,否則會報錯。
注意:如上面說明,local 指令本身會傳回一個值,正常的傳回值是 0。假設有個 testlocal.sh 腳本,内容如下:
#!/bin/bashfoo() { return 1; }bar() { ret=$(foo); echo first: $? local var=$(foo); echo second: $?}foobar() { return 0; }barlocal out=$(foobar); echo third: $?
則執行 ./testlocal.sh 腳本,會輸出:
first: 1second: 0./testlocal.sh: 第 x 行:local: 隻能在函數中使用third: 1
可以看到,ret=$(foo); 語句沒有使用 local 指令來定義 ret 變量,執行 foo 函數,該函數的傳回值是 1,是以得到的 $? 是 1。
而 local var=$(foo); 語句使用 local 指令來定義 var 變量,執行 foo 函數,得到的 $? 卻是 0,而foo 函數明明傳回的是 1。原因就是該語句先通過 $(foo) 執行 foo 函數,然後用 local var 來定義 var 變量為局部變量,是以該語句對應的 $? 是 local 指令的傳回值,而不是 foo 函數的傳回值。
當在函數外執行 local 指令時,它會報錯,可以看到雖然 foobar 函數傳回是 0,但是第三個 echo 語句列印的 $?是 1,正好是 local 指令執行出錯時的傳回值。
即,對于 local var=$(func); 這種語句來說,它對應的 $? 不是所調用函數的傳回值,而是local 指令的傳回值。是以執行函數後,想用 $? 來判斷函數的 return 傳回值時,注意不要用這種寫法。
為了避免這種情況,最好在函數開頭就用 local 指令聲明所有局部變量。
使用 local 聲明多個變量時,變量之間用空格隔開,不要加逗号。舉例如下:
local a b c;
總的來說,在函數内使用 local 指令來聲明局部變量是一個好的程式設計習慣,避免變量同名造成的幹擾。
PS:未完待續,下篇文章會繼續說明,敬請期待~