在 Bash shell 腳本中,函數是一種組合一系列指令以獲得特定結果的方法。函數可以被認為是迷你腳本。在某些編程語言中,函數也稱為過程和方法。函數是實現模塊化和可重用性的好方法。
本文通過示例展示瞭如何在 Linux 上使用函數 bash 腳本。到本文結束時,您應該能夠熟練使用 bash 的特性。
內容
如何在 Bash 中定義函數
使用函數時,有兩件重要的事情需要理解。
- 定義一個函數,
- 調用一個函數。
類似於 bash 腳本的編寫和運行方式,您需要定義一個函數並調用它來運行該函數。
定義 bash 函數有兩種句法方式。第一種方法是通過 bash 內置關鍵字。 "function"
後跟函數名稱。代碼塊寫在裡面 大括號 {}
.
function [name] {
Block of code
}
第二種方法是創建不帶關鍵字的函數。 "function"
. 它以函數名開頭,後跟圓括號。
[name](){
Block of Code
}
你選擇哪個?好吧,這始終是個人選擇。選擇其中之一沒有任何缺點。
您還可以編寫一個被調用的單行函數。 緊湊的功能compact 函數將花括號內的每一行代碼替換為 分號 (;
).
啟動終端並編寫多行函數。如果您現在按向上箭頭鍵,您會看到多行描述已轉換為一個緊湊的函數。
[name](){ first_line; second_line; }
最佳實踐:
- 選擇一種語法並儘量保持一致。
- 在協作環境中工作時,每個人在編碼時保持相同的標準非常重要。
命名約定
當你創建一個函數時,你必須給它一個名字。函數名稱應該是描述性的,避免名稱已經被其他函數、變量、常量等使用。 “蛇案” 是命名函數的推薦方法。對於蛇,單詞之間用下劃線分隔。
請參見下面的示例。我創建了一個名為 "hello_world"
在 snake case 風格中,它只是將 hello world 打印到 stdout(終端)。
hello_world() {
echo "Running Simple Hello World Function"
}
hello_world
如何在 Bash 中調用函數
讓我們創建一個簡單的清理函數,稱為 "log_cleanup"
這個函數的目的是 ".log"
超過 30 天的文件。
log_cleanup(){ echo "Running Cleanup On Older Logs - 30 days" find /home/karthick/Documents/Projects/logs/ -name "*.log" -type f -mtime +30 -delete echo "Cleanup Completed" }
函數已定義,但函數是否足以勝任這項工作?絕對不是。您必須為要運行的函數調用該函數。
要調用函數,請在函數定義後輸入函數名稱。
#!/usr/bin/env bash #### FUNCTION DEFINITION #### log_cleanup(){ echo "Running Cleanup On Older Logs - 30 days" find /home/karthick/Documents/Projects/logs -name "*.log" -type f -mtime +30 -delete echo "Cleanup Completed" } # Calling the function log_cleanup
如果我嘗試在定義函數之前調用它,我會收到以下錯誤:
line 3: log_cleanup: command not found

為什麼會這樣?運行腳本時,代碼會從上到下逐行解釋。讀取函數並將其加載到 bash 環境(內存)中。但是在這裡,您是在解釋器讀取函數並將其加載到環境中之前調用該函數。
當從另一個函數中調用一個函數時,函數定義可以按任何順序排列,但第一個除外。見下圖。功能 特徵2 稱為 功能 1 什麼時候 特色三 稱為 特徵2 在他們的定義之前。然而 功能 1 先定義,再調用。到……的時候 功能 1 所有被調用的函數定義都已經被解釋並加載到環境中。

退出狀態和返回值
所有 Linux 命令都返回退出狀態 (0-255)。零被認為是成功,其餘的退出代碼被認為是具有各種含義的失敗。類似地,執行一個函數會返回在該函數中執行的最後一個命令的退出狀態。
讓我再次運行相同的“清理”功能。但是我給的路徑在我的機器上不可用,所以 find
命令失敗。我在用 $?
獲取腳本中的退出狀態,如圖所示。
Running Cleanup On Older Logs - 30 days find: '/home/karthick/Documents/Projectss/logs': No such file or directory Cleanup Completed Exit status of function log_cleanup is ⇒ 0

函數返回的退出狀態是 echo
該命令作為函數內的最後一個命令執行。這不是預期的行為。
要克服這種行為,您可以使用內置的 bash。 "return"
陳述。
$ type -a return
return is a shell builtin
返回一個整數 [N] 獲取值,退出函數,並將返回值提供給調用者(函數)。 在使用 return 語句之前,您應該了解有關如何使用它的一些規則。如前所述,return 接受 0 到 255 之間的整數值。如果未傳遞任何參數(整數值)或值大於 255,則 return 語句使用最後執行的命令的退出狀態。
請讓我通過退貨來解決 "cleanup"
功能行為。這裡我們使用帶有返回命令的條件語句。
#!/usr/bin/env bash #### FUNCTION DEFINITION #### log_cleanup(){ echo "[ INFO ] - Running Cleanup On Older Logs - 30 days" if [[ -d "/home/karthick/Documents/Projectss/logs" ]] then find -name "*.log" -type f -mtime +30 -delete echo "[ SUCCESS] - Cleanup Completed" else echo "[ ERROR ] - Directory path wrong... Cleanup has not happened..." return 1 fi } # Calling the function log_cleanup echo "++ Exit status of log_cleanup function is ==> $?"
請參閱下面的輸出。返回函數 退出代碼 1 從返回語句。
[ INFO ] - Running Cleanup On Older Logs - 30 days
[ ERROR ] - Directory path wrong… Cleanup has not happened…
++ Exit status of log_cleanup function is ==> 1

將參數傳遞給函數
就像將參數傳遞給 bash 腳本一樣,函數也接受參數。令人困惑的部分是函數使用相同的 $1
……$9
用於訪問參數的特殊變量。這與將參數傳遞給腳本相同。我需要了解在函數內部或外部使用這個特殊變量時會發生什麼。
cat > arg_test.sh #!/bin/bash echo "Value passed in $1 is = $1" howdy(){ echo "value of $1 inside function is = $1" } howdy # Function Call
複製上面的代碼片段並運行它以查看差異。細繩 "Howdy"
作為第一個參數傳遞給腳本。
$ ./arg_test.sh howdy
Value passed in $1 is = howdy
value of $1 inside function is =
從輸出中我們可以看到: $1
由於函數內部輸出了空值, $1
函數內部是不同的 $1
它們共享相同的名稱,但在功能之外。
要將參數傳遞給函數,請在函數名稱後留一個空格並傳遞參數,如下圖所示。每個以空格分隔的參數都分配給其各自的變量 $1
……$N
您可以在函數內部使用此變量來處理參數。
log_cleanup $1 $2 ….. $N

正如您在上面的屏幕截圖中看到的,我將目錄名稱和天數作為參數傳遞。
函數變量作用域
一旦在函數內部或外部創建了一個變量,就可以全局訪問它。默認情況下,變量是在全局範圍內創建的。
請參見下面的示例。 當我嘗試訪問這兩個變量時, outside_function
什麼時候 inside_function
,您可以訪問這些值。這意味著即使在函數執行並退出後,也可以在全局範圍內訪問在函數內創建的變量。
#!/bin/bash outside_function="This variable is from outside the function" func1(){ inside_function="This variable is from inside the func1" } func1 echo $outside_function echo $inside_function

在某些編程語言中這可能行不通。在函數內創建的變量在函數執行期間可用。但在 bash 中它的工作方式不同。
要使變量成為函數的局部變量,您可以使用 bash 內置函數。 "local"
關鍵詞。 local 關鍵字將變量的範圍從全局限制為局部,只允許在函數運行時訪問變量。
#!/bin/bash
outside_function="This variable is from outside the function"
func1(){
local inside_function="This variable is from inside the func1"
}
func1
echo $outside_function
echo $inside_function

推薦閱讀:
- Bash 腳本 – 示例中解釋的變量
使用 local 關鍵字允許在不同的函數中使用相同的變量名。

筆記: 始終避免使用已經使用過的變量、函數和 bash 關鍵字。上面的例子是為了理解它是如何工作的。
模塊化和可重用性
理解和編寫函數很簡單。但是需要時間來更好地了解您的環境以創建出色的功能。正如在介紹部分已經指出的那樣,bash 的特性極大地提高了模塊化和可重用性。
讓我們看一個例子。 我創建了 20 個腳本並包含在每個腳本中 log_cleanup
上一節中用於執行內務處理任務的函數。 您可以創建一個函數定義並將其導入 20 個腳本,而不是將函數包含在所有 20 個腳本中。通過這種方式,我們實現了模塊化和可重用的功能。這很相似 進口 Python 中的語句, 包括 語句如 C
見下圖。我創建了兩個腳本。 script1.sh
什麼時候 script2.sh
什麼時候 log_cleanup
這些函數寫在一個單獨的文件中,名為 cleanup.sh
.

通過運行導入函數 source
命令。這個 source
該命令將運行作為參數傳遞的文件,並將任何變量或函數加載到當前 bash 會話中。當你跑步時 log_cleanup
從另一個腳本文件中,該函數已經加載到當前環境中並且可以訪問。

從上圖中您可以看到參數如何提供幫助。只有一個函數定義。根據您的用例,您可以修改函數以接受不同的參數和不同的腳本。
筆記: 您還可以運行 shell 腳本 source
命令在當前 shell 中運行腳本,而不是創建子 shell 來運行腳本。
結論是
本指南通過示例討論了 Bash 函數,以及如何在腳本中定義和調用它們。要熟悉功能,您需要通過不同的用例來練習它們。如果您有任何問題或意見,請隨時在下面的評論部分告訴我們。
相關文件:
- Bash 腳本 – For 循環示例說明
- Bash 腳本 – 如示例中所述的 while 和 until 循環
- 使用和不使用導出定義 Bash 變量之間的差異
- Bash Echo 命令用 Linux 示例說明
- Bash Heredoc 初學者教程
- Bash 重定向示例解釋
BASHBash 函數Bash 腳本Bash PromptCLICommandlineLinuxScriptingShell 腳本