Bash與”真正的”編程語言一樣,Bash也有函數,雖然在某些實現方面稍有限制。一個函數就是一個子程序,用於實現一系列操作的代碼塊,它是完成特定任務的”黑盒子”。當存在重複代碼的時候,或者當一個任務只需要輕微修改就被重複使用的時候,就需要考慮使用函數了。
函數定義
定義函數有兩種方法:
function foo() {
#1
}
foo() {
#2 這種方法和c語言更加貼近,兼容性也更好。
}
需要注意的是函數的定義需要在使用之前。
函數參數
在調用函數的時候可以給函數傳遞參數。
如:
foo "bar"
如何在函數中使用這些參數呢,Bash中有特定的符號來表示各個參數。
$0
就是腳本文件自身的名字,$1
是第一個參數,$2
是第二個參數,$3
是第三個參數,以此類推。需要注意的是9以上的參數爲了避免Bash解析錯誤,需要加上大括號或者雙引號(使用${10}
,防止其被解析爲${1}0
的形式)。$*
表示這個程式的所有參數。$#
表示這個程式的參數個數。
關於函數中變量的聲明:如果變量用local來聲明, 那麼它就只能夠在該變量被聲明的代碼塊中可見。這個代碼塊就是局部”範圍”。在一個函數中, 一個局部變量只有在函數代碼塊中才有意義。
函數的返回值
Bash函數中的return關鍵字會返回這個函數的退出狀態碼(shell中不區分變量的類型。但是shell會區分這個變量是整形還是字符串,其關鍵就是這個變量的值中是否只有數字。如果是整形則可以使用算數運算符對其進行計算。)。調用者可以通過讀取$?
來獲取函數的退出狀態碼變量($?
變量保存了一個命令,一個函數,或者是腳本本身的退出狀態碼)。我們可以通過設置全局變量或者使用命令替換。
下面這個簡單的例子使用全局變量的方法進行了返回值的傳遞。
function foo() {
r="sometext"
}
foo
echo "$r"
這種做法雖然很簡單方便,但是過多的定義全局變量將會導致這個程序的維護成本急劇增加。
更好的方法是在函數中使用local
變量,然後再結合命令替換的方式來把想傳遞的值傳給調用者:
function foo() {
local r="sometext"
echo "$r"
}
result=$(foo) #等價於result=`foo`
echo "$result"
在這個例子中結果被輸出到stdout
中,這樣的話調用者就可以通過命令替換來獲取返回值了。
還有一種方法可以進行值的返回,調用者可以將變量的名字傳給函數,然後函數將返回值存儲到這個名字的變量之中,這樣調用者就可以直接通過訪問這個變量來獲取返回值了。
function myfunc()
{
local r=$1
local myresult='some text'
eval $r="'$myresult'"
}
myfunc result
echo $result
被一對雙引號(” “)括起來的變量替換是不會被阻止的。所以雙引號被稱爲部分引用,有時候又被稱爲”弱引用”。但是如果使用單引號的話(’ ‘), 那麼變量替換就會被禁止了,變量名只會被解釋成字面的意思,不會發生變量替換。所以單引號被稱爲全引用,有時候也被稱爲”強引用”。所以在以上的例子中要使用some text作爲值的時候就不能使用”some text”,空格會引起腳本執行錯誤,只能使用’some text’。
在上面的例子中eval
會讓shell先對$r="'$myresult'"
就行一次掃描和替換,變成result='some text'
。然後在正式運行函數的時候就會把’some text’賦值給result變量,這樣調用者在來訪問result變量就可以取得函數的返回值了。