Linux 命令行與 shell 腳本編程大全 17 創(chuàng)建函數(shù)

介紹如何在 shell 腳本中創(chuàng)建函數(shù),以及如何在 shell 腳本中使用這些函數(shù)

更多精彩

導(dǎo)覽

  1. 為了提高腳本中代碼的重用性,可以將指定代碼塊封裝為一個函數(shù),然后在腳本中通過函數(shù)的名稱對函數(shù)進行調(diào)用
  2. 腳本函數(shù)可以用函數(shù)最后一條命令的退出狀態(tài)碼或 return 命令來返回指定數(shù)值,范圍在 0-255 之間
  3. 函數(shù)也可以使用 echo 語句輸出返回值,這可以讓函數(shù)的返回值不局限于數(shù)值
  4. 可以再函數(shù)中使用 shell 變量,函數(shù)的變量分為 全局變量局部變量 ,局部變量 需要添加 local 前綴
  5. 函數(shù)可以調(diào)用包裹其自身在內(nèi)的其他函數(shù),函數(shù)調(diào)用自身的方式叫做 遞歸
    • 在使用遞歸時必須設(shè)置一個終結(jié)條件,否則會導(dǎo)致無限循環(huán)
  6. 使用 函數(shù)庫文件 可以實現(xiàn)函數(shù)在不同腳本中的調(diào)用,只需要在調(diào)用的腳本中使用 source 命令引入指定 函數(shù)庫文件 即可
  7. 可以直接在命令行創(chuàng)建和調(diào)用函數(shù),也可以將函數(shù)寫在 .bashrc ,實現(xiàn)函數(shù)的全局調(diào)用
  8. 函數(shù)庫文件.bashrc 中進行 source 命令的調(diào)用,也可以實現(xiàn)函數(shù)的全局調(diào)用

17.1 基本的腳本函數(shù)

  1. 函數(shù)是一個腳本代碼塊,可以為其指定一個名稱并在腳本中進行調(diào)用

17.1.1 創(chuàng)建函數(shù)

  1. 腳本中每個函數(shù)的名稱都不能重復(fù)

17.1.1.1 基本語法

function name {
  commands
}

17.1.1.2 簡寫語法

name() {
  commands
}

17.1.2 使用函數(shù)

  1. 在腳本中創(chuàng)建函數(shù)后,就可以在后續(xù)代碼中進行調(diào)用,如下圖
  2. 需要注意的是,函數(shù)并不是必須得在腳本的開始位置進行創(chuàng)建 ,但是 函數(shù)必須在其被調(diào)用之前創(chuàng)建
  3. 如果函數(shù)的創(chuàng)建語句在其調(diào)用語句之后,shell 會因為找不到被調(diào)用的函數(shù)而拋出異常


17.1.2.1 函數(shù)名稱的唯一性

  1. 如果在腳本中定義了重名的函數(shù),那么新定義的函數(shù)會覆蓋之前的函數(shù),如下圖


17.2 返回值

17.2.1 默認退出狀態(tài)碼

  1. 11.8.1 查看退出狀態(tài)碼 中已經(jīng)介紹過退出狀態(tài)碼的概念,常見的退出狀態(tài)碼可以參考下圖
  2. 默認情況下, 函數(shù)的退出狀態(tài)碼時函數(shù)中最后一條命令返回的退出狀態(tài)碼
  3. 在函數(shù)執(zhí)行完畢后,可以立即用標(biāo)準(zhǔn)變量 $? 來確定函數(shù)的退出狀態(tài)碼,如下圖
    • 可以看到,在 exitCode 函數(shù)的最后使用 ls badDir 查詢了一個不存在的目錄
    • 那么該命令的退出狀態(tài)碼肯定是 1 ,使用 $? 可以正常獲取到該值
  4. 但是如果有異常的命令不是最后一條命令,則無法得知該命令的執(zhí)行結(jié)果,如下圖
    • 相對于上一個腳本,該腳本只是將函數(shù)內(nèi)部的兩個命令互換了位置
    • 但是得到的函數(shù)返回值卻截然相反,所以這種直接通過 $? 獲取函數(shù)返回值的方式,沒有多少實用意義

17.2.2 使用 return 命令

  1. 使用 return 命令可以退出函數(shù),并返回特定的退出狀態(tài)碼
  2. return 命令允許指定一個整數(shù)值來自定義函數(shù)的退出狀態(tài)碼,如下圖

17.2.2.1 使用退出狀態(tài)碼作為函數(shù)返回值的缺陷

  1. 要獲取退出狀態(tài)碼需要使用 $? ,而且需要在函數(shù)執(zhí)行之后立即使用,如果在其中穿插了其他命令,就無法獲取到函數(shù)最后一條命令的退出狀態(tài)碼
  2. 退出狀態(tài)碼的取值范圍是 0-255 ,不在這個范圍內(nèi)的值無法作為退出狀態(tài)碼來賦予函數(shù)返回值

17.2.3 使用函數(shù)輸出

  1. 函數(shù)可以將 echo 的輸出內(nèi)容作為函數(shù)的返回值,如下圖
    • 函數(shù)中的 echo 語句雖然輸出了一句話,但函數(shù)被調(diào)用后,這句話并沒有立即輸出
    • 它作為函數(shù)的返回值被保存到了 result 變量中,直到該變量被 echo 使用時,函數(shù)的返回值才被輸出
    • 而且可以看到,使用這種方式時,函數(shù)的返回值不局限于數(shù)字


17.3 在函數(shù)中使用變量

17.3.1 向函數(shù)傳遞參數(shù)

  1. 可以使用給腳本傳參的方式給函數(shù)傳參,函數(shù)內(nèi)部對于傳入?yún)?shù)的調(diào)用方式也和腳本中調(diào)用保持一致,如下圖


17.3.2 在函數(shù)中處理變量

  1. 在函數(shù)中可以使用 全局變量 ,以及 局部變量
    • 函數(shù)中定義的 局部變量 對于函數(shù)以外的部分,是不可見的

17.3.2.1 全局變量

  1. 默認情況下,在腳本中定義的任何變量都是全局變量

17.3.2.2 局部變量

  1. 使用 local 關(guān)鍵字聲明的變量就是局部變量,該變量只能在其聲明的函數(shù)內(nèi)部才能訪問,如下圖
    • 兩個 result 變量,雖然名稱相同,但由于函數(shù)內(nèi)部的是局部變量,所以互不影響

17.4 數(shù)組變量和函數(shù)

17.4.1 向函數(shù)傳遞數(shù)組參數(shù)

  1. 如果試圖直接將數(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ù)

  1. 想要讓函數(shù)能夠獲取到完整的數(shù)組內(nèi)容,需要先將數(shù)據(jù)的內(nèi)容分解成為普通的參數(shù)列表
  2. 然后在函數(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)容

17.4.2 從函數(shù)返回數(shù)組

  1. 其實和將數(shù)組作為普通參數(shù)傳入到函數(shù)中一樣
  2. 想要從函數(shù)內(nèi)部返回數(shù)組,只需要將函數(shù)內(nèi)部的數(shù)組作為普通參數(shù)輸出即可,如下圖


17.5 函數(shù)遞歸

  1. 遞歸其實就是函數(shù)自己調(diào)用自己,但必須為遞歸準(zhǔn)備一個最終條件,否則會導(dǎo)致無限循環(huán)
  2. 遞歸算法的經(jīng)典例子是計算階乘,例如 5! = 1 * 2 * 3 * 4 * 5 = 120 ,公式是 x! = (x * (x -1))!
  3. 用腳本來表示的話,如下圖


17.6 創(chuàng)建庫

  1. 利用 函數(shù)庫文件 可以實現(xiàn)一個函數(shù)在不同的腳本中被重復(fù)調(diào)用
  2. 使用 source 命令可以在指定腳本中調(diào)用 函數(shù)庫文件
    • 默認情況下,由于 shell 函數(shù)作用域的限制,函數(shù)只會在其被定義的腳本中生效
    • 但是 source 命令會在當(dāng)前 shell 上下文中執(zhí)行命令,而不是創(chuàng)建一個新 shell ,相當(dāng)于把目標(biāo)腳本解析到了當(dāng)前腳本中
  3. source 命令的語法分兩種
    • 完整語法 source ./file
    • 簡寫語法 . ./file
  4. 寫一個簡單例子演示一下,如下圖


17.7 在命令行上使用函數(shù)

17.7.1 在命令行上創(chuàng)建函數(shù)

  1. 使用這種方式創(chuàng)建的函數(shù)都是臨時的,一旦當(dāng)前 shell 退出,這些被創(chuàng)建的函數(shù)都將不復(fù)存在
  2. 而且這種方式不但沒有什么實際意義,還非常危險,如果誤將函數(shù)的名稱和當(dāng)前系統(tǒng)中其他命令的名稱重名了,那么這個系統(tǒng)命令將會被覆蓋

17.7.1.1 單行定義函數(shù)

  1. 其實就是將一個簡單的的函數(shù)直接在命令行上進行創(chuàng)建,如下圖
    • 在每個命令的最后都需要添加分號,這樣 shell 才會知道命令的開始和結(jié)束在什么時候發(fā)生


17.7.1.2 多行定義函數(shù)

  1. 使用 shell 的 次提示符( > ) 來輸入更多命令,如下圖
    • 當(dāng)輸入 { 后按下回車,會直接進入函數(shù)的多行模式
    • 當(dāng)輸入 } 后按下回車,會直接退出函數(shù)的多行模式

17.7.2 在 .bashrc 文件中定義函數(shù)

  1. 因為 .bashrc 文件是的特性,用戶在開啟每個 shell 進程時,系統(tǒng)都會掃描該文件
  2. 所以可以把該文件作為一個默認的 全局函數(shù)庫文件 ,將函數(shù)直接寫在這個文件中,將可以直接實現(xiàn)函數(shù)的全局調(diào)用
  3. 但該文件中也會存在一些系統(tǒng)預(yù)置的內(nèi)容,所以直接添加各種自定義函數(shù),容易導(dǎo)致文件內(nèi)容變的混亂
  4. 所以也可以使用 source 命令將一些自定義的 函數(shù)庫文件 ,在該文件的末尾進行引用

17.8 實例

  1. 介紹 GNU shtool shell 腳本函數(shù)庫如何安裝和使用,跳過了
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容