介紹如何在 shell 腳本中創(chuàng)建函數(shù),以及如何在 shell 腳本中使用這些函數(shù)
更多精彩
- 更多技術(shù)博客,請移步 IT人才終生實訓(xùn)與職業(yè)進階平臺 - 實訓(xùn)在線
導(dǎo)覽
- 為了提高腳本中代碼的重用性,可以將指定代碼塊封裝為一個函數(shù),然后在腳本中通過函數(shù)的名稱對函數(shù)進行調(diào)用
- 腳本函數(shù)可以用函數(shù)最后一條命令的退出狀態(tài)碼或
return命令來返回指定數(shù)值,范圍在 0-255 之間 - 函數(shù)也可以使用
echo語句輸出返回值,這可以讓函數(shù)的返回值不局限于數(shù)值 - 可以再函數(shù)中使用 shell 變量,函數(shù)的變量分為 全局變量 和 局部變量 ,局部變量 需要添加
local前綴 - 函數(shù)可以調(diào)用包裹其自身在內(nèi)的其他函數(shù),函數(shù)調(diào)用自身的方式叫做 遞歸
- 在使用遞歸時必須設(shè)置一個終結(jié)條件,否則會導(dǎo)致無限循環(huán)
- 使用 函數(shù)庫文件 可以實現(xiàn)函數(shù)在不同腳本中的調(diào)用,只需要在調(diào)用的腳本中使用
source命令引入指定 函數(shù)庫文件 即可 - 可以直接在命令行創(chuàng)建和調(diào)用函數(shù),也可以將函數(shù)寫在 .bashrc ,實現(xiàn)函數(shù)的全局調(diào)用
- 將 函數(shù)庫文件 在 .bashrc 中進行
source命令的調(diào)用,也可以實現(xiàn)函數(shù)的全局調(diào)用
17.1 基本的腳本函數(shù)
- 函數(shù)是一個腳本代碼塊,可以為其指定一個名稱并在腳本中進行調(diào)用
17.1.1 創(chuàng)建函數(shù)
- 腳本中每個函數(shù)的名稱都不能重復(fù)
17.1.1.1 基本語法
function name {
commands
}
17.1.1.2 簡寫語法
name() {
commands
}
17.1.2 使用函數(shù)
- 在腳本中創(chuàng)建函數(shù)后,就可以在后續(xù)代碼中進行調(diào)用,如下圖
- 需要注意的是,函數(shù)并不是必須得在腳本的開始位置進行創(chuàng)建 ,但是 函數(shù)必須在其被調(diào)用之前創(chuàng)建
-
如果函數(shù)的創(chuàng)建語句在其調(diào)用語句之后,shell 會因為找不到被調(diào)用的函數(shù)而拋出異常
17.1.2.1 函數(shù)名稱的唯一性
-
如果在腳本中定義了重名的函數(shù),那么新定義的函數(shù)會覆蓋之前的函數(shù),如下圖
17.2 返回值
17.2.1 默認退出狀態(tài)碼
- 在 11.8.1 查看退出狀態(tài)碼 中已經(jīng)介紹過退出狀態(tài)碼的概念,常見的退出狀態(tài)碼可以參考下圖
- 默認情況下, 函數(shù)的退出狀態(tài)碼時函數(shù)中最后一條命令返回的退出狀態(tài)碼
- 在函數(shù)執(zhí)行完畢后,可以立即用標(biāo)準(zhǔn)變量
$?來確定函數(shù)的退出狀態(tài)碼,如下圖- 可以看到,在
exitCode函數(shù)的最后使用ls badDir查詢了一個不存在的目錄 - 那么該命令的退出狀態(tài)碼肯定是 1 ,使用
$?可以正常獲取到該值
- 可以看到,在
- 但是如果有異常的命令不是最后一條命令,則無法得知該命令的執(zhí)行結(jié)果,如下圖
- 相對于上一個腳本,該腳本只是將函數(shù)內(nèi)部的兩個命令互換了位置
- 但是得到的函數(shù)返回值卻截然相反,所以這種直接通過
$?獲取函數(shù)返回值的方式,沒有多少實用意義
17.2.2 使用 return 命令
- 使用
return命令可以退出函數(shù),并返回特定的退出狀態(tài)碼 -
return命令允許指定一個整數(shù)值來自定義函數(shù)的退出狀態(tài)碼,如下圖
17.2.2.1 使用退出狀態(tài)碼作為函數(shù)返回值的缺陷
- 要獲取退出狀態(tài)碼需要使用
$?,而且需要在函數(shù)執(zhí)行之后立即使用,如果在其中穿插了其他命令,就無法獲取到函數(shù)最后一條命令的退出狀態(tài)碼 - 退出狀態(tài)碼的取值范圍是 0-255 ,不在這個范圍內(nèi)的值無法作為退出狀態(tài)碼來賦予函數(shù)返回值
17.2.3 使用函數(shù)輸出
- 函數(shù)可以將
echo的輸出內(nèi)容作為函數(shù)的返回值,如下圖- 函數(shù)中的
echo語句雖然輸出了一句話,但函數(shù)被調(diào)用后,這句話并沒有立即輸出 - 它作為函數(shù)的返回值被保存到了 result 變量中,直到該變量被
echo使用時,函數(shù)的返回值才被輸出 -
而且可以看到,使用這種方式時,函數(shù)的返回值不局限于數(shù)字
- 函數(shù)中的
17.3 在函數(shù)中使用變量
17.3.1 向函數(shù)傳遞參數(shù)
-
可以使用給腳本傳參的方式給函數(shù)傳參,函數(shù)內(nèi)部對于傳入?yún)?shù)的調(diào)用方式也和腳本中調(diào)用保持一致,如下圖
17.3.2 在函數(shù)中處理變量
- 在函數(shù)中可以使用 全局變量 ,以及 局部變量
- 函數(shù)中定義的 局部變量 對于函數(shù)以外的部分,是不可見的
17.3.2.1 全局變量
- 默認情況下,在腳本中定義的任何變量都是全局變量
17.3.2.2 局部變量
- 使用
local關(guān)鍵字聲明的變量就是局部變量,該變量只能在其聲明的函數(shù)內(nèi)部才能訪問,如下圖- 兩個 result 變量,雖然名稱相同,但由于函數(shù)內(nèi)部的是局部變量,所以互不影響
- 兩個 result 變量,雖然名稱相同,但由于函數(shù)內(nèi)部的是局部變量,所以互不影響
17.4 數(shù)組變量和函數(shù)
17.4.1 向函數(shù)傳遞數(shù)組參數(shù)
- 如果試圖直接將數(shù)組作為參數(shù)傳遞到函數(shù)中,將無法得到完整的數(shù)組內(nèi)容,只能得到數(shù)組的第一個值,如下圖
- 正常的使用
${array[*]}可以獲取到數(shù)組的全部內(nèi)容 -
但是將數(shù)組作為一般參數(shù)傳入到函數(shù)中后,不論如何操作,都只能獲取到數(shù)組的第一個值,所以數(shù)組不能作為一般參數(shù)直接傳入函數(shù)
- 正常的使用
17.4.1.1 將數(shù)組內(nèi)容分解后傳入函數(shù)
- 想要讓函數(shù)能夠獲取到完整的數(shù)組內(nèi)容,需要先將數(shù)據(jù)的內(nèi)容分解成為普通的參數(shù)列表
- 然后在函數(shù)中對傳入的所有參數(shù)進行重新組裝,獲取一個新的數(shù)組,如下圖
- 將數(shù)組傳入函數(shù)時使用的
arrayParam ${array[*]},其實就是將數(shù)組的輸出結(jié)果1 2 3作為普通參數(shù)全部傳給函數(shù)- 完整形式就是
arrayParam 1 2 3
- 完整形式就是
- 然后在函數(shù)內(nèi)容使用
($(echo "$@"))將參數(shù)一次性輸出,并包裝成為數(shù)組內(nèi)容
- 將數(shù)組傳入函數(shù)時使用的
17.4.2 從函數(shù)返回數(shù)組
- 其實和將數(shù)組作為普通參數(shù)傳入到函數(shù)中一樣
-
想要從函數(shù)內(nèi)部返回數(shù)組,只需要將函數(shù)內(nèi)部的數(shù)組作為普通參數(shù)輸出即可,如下圖
17.5 函數(shù)遞歸
- 遞歸其實就是函數(shù)自己調(diào)用自己,但必須為遞歸準(zhǔn)備一個最終條件,否則會導(dǎo)致無限循環(huán)
- 遞歸算法的經(jīng)典例子是計算階乘,例如
5! = 1 * 2 * 3 * 4 * 5 = 120,公式是x! = (x * (x -1))! -
用腳本來表示的話,如下圖
17.6 創(chuàng)建庫
- 利用 函數(shù)庫文件 可以實現(xiàn)一個函數(shù)在不同的腳本中被重復(fù)調(diào)用
- 使用
source命令可以在指定腳本中調(diào)用 函數(shù)庫文件- 默認情況下,由于 shell 函數(shù)作用域的限制,函數(shù)只會在其被定義的腳本中生效
- 但是
source命令會在當(dāng)前 shell 上下文中執(zhí)行命令,而不是創(chuàng)建一個新 shell ,相當(dāng)于把目標(biāo)腳本解析到了當(dāng)前腳本中
-
source命令的語法分兩種- 完整語法
source ./file - 簡寫語法
. ./file
- 完整語法
-
寫一個簡單例子演示一下,如下圖
17.7 在命令行上使用函數(shù)
17.7.1 在命令行上創(chuàng)建函數(shù)
- 使用這種方式創(chuàng)建的函數(shù)都是臨時的,一旦當(dāng)前 shell 退出,這些被創(chuàng)建的函數(shù)都將不復(fù)存在
- 而且這種方式不但沒有什么實際意義,還非常危險,如果誤將函數(shù)的名稱和當(dāng)前系統(tǒng)中其他命令的名稱重名了,那么這個系統(tǒng)命令將會被覆蓋
17.7.1.1 單行定義函數(shù)
- 其實就是將一個簡單的的函數(shù)直接在命令行上進行創(chuàng)建,如下圖
-
在每個命令的最后都需要添加分號,這樣 shell 才會知道命令的開始和結(jié)束在什么時候發(fā)生
-
17.7.1.2 多行定義函數(shù)
- 使用 shell 的 次提示符( > ) 來輸入更多命令,如下圖
- 當(dāng)輸入
{后按下回車,會直接進入函數(shù)的多行模式 - 當(dāng)輸入
}后按下回車,會直接退出函數(shù)的多行模式
- 當(dāng)輸入
17.7.2 在 .bashrc 文件中定義函數(shù)
- 因為 .bashrc 文件是的特性,用戶在開啟每個 shell 進程時,系統(tǒng)都會掃描該文件
- 所以可以把該文件作為一個默認的 全局函數(shù)庫文件 ,將函數(shù)直接寫在這個文件中,將可以直接實現(xiàn)函數(shù)的全局調(diào)用
- 但該文件中也會存在一些系統(tǒng)預(yù)置的內(nèi)容,所以直接添加各種自定義函數(shù),容易導(dǎo)致文件內(nèi)容變的混亂
- 所以也可以使用
source命令將一些自定義的 函數(shù)庫文件 ,在該文件的末尾進行引用
17.8 實例
- 介紹 GNU shtool shell 腳本函數(shù)庫如何安裝和使用,跳過了















