當你的 bash 腳本中代碼非常多的時候,會看起來很混亂,其中有部分代碼有可能是重復的。這個時候,可以使用函數來避免重復的代碼。
今天我們將介紹在 bash 中如何創建函數,以及函數中的返回值、傳遞參數等內容。
在 bash 中創建函數
創建 bash 函數有兩種不同的語法。最常用的方法如下:
function_name () {
commands
}
第二種方法不太常用,如下所示:
function function_name {
commands
}
在使用函數時,需要注意以下幾點:
- 除非被調用,否則函數永遠不會被執行;
- 函數必須先定義,然后才能被調用。
作為演示,我們創建一個 fun.sh 腳本,如下代碼:
#!/bin/bash
hello () {
echo "Hello World"
}
hello
hello
hello
上述腳本中,我們定義了一個名為 hello 的函數,它將在終端上打印 Hello World。后面我們調用了三次 hello 函數,因此,運行腳本后,你會在屏幕上看到 Hello World 打印了三次:
$ ./fun.sh
Hello World
Hello World
Hello World
函數的返回值
在很多編程語言中,函數在調用時都會返回一個值,然而,在 bash 函數中沒有返回值。
當函數執行完成時,會返回一個 $? 變量作為退出狀態,0 表示成功執行,其他非零正整數(1 - 255)表示執行失敗。
我們來寫一個例子,命名為 error.sh,在其中寫一個 return 語句,如下代碼所示:
#! /bin/bash
error () {
blabla
return 0
}
error
echo "The return status of the error function is: $?"
執行結果如下:
$ ./error.sh
./error.sh: line 4: blabla: command not found
The return status of the error function is: 0
因為有 return 0 這一行,所以即使函數中有 blabla 這一行的報錯,error 函數還是返回了一個執行成功的狀態碼 0。
return 語句執行后,函數會被立即終止。
向 bash 函數傳遞參數
我們可以向函數傳遞參數,就像向 bash 腳本傳遞參數一樣。
作為演示,我們創建一個名為 iseven.sh 的腳本,如下所示:
#!/bin/bash
iseven () {
if [ $(($1 % 2)) -eq 0 ]; then
echo "$1 is even."
else
echo "$1 is odd."
fi
}
iseven 3
iseven 4
iseven 20
iseven 111
iseven() 函數判斷數字是偶數還是奇數。在調用的時候,將參數放在函數名后面,函數執行的時候會讀取 $1 來獲取傳遞的參數。我們來執行一下:
$ ./iseven.sh
3 is odd.
4 is even.
20 is even.
111 is odd.
這里需要注意,bash 函數中的參數,和 bash 腳本的參數需要區分開來,看如下 funarg.sh 腳本:
#!/bin/bash
fun () {
echo "$1 is the first argument to fun()"
echo "$2 is the second argument to fun()"
}
echo "$1 is the first argument to the script."
echo "$2 is the second argument to the script."
fun Yes 7
執行結果如下:
$ ./funarg.sh Cool Stuff
Cool is the first argument to the script.
Stuff is the second argument to the script.
Yes is the first argument to fun()7 is the second argument to fun()
可以看到,同樣是使用 $1 和 $2 來引用腳本參數和函數參數,當實際調用時,取值是不同的。
bash 函數中的全局變量和局部變量
與大多數編程語言累死,bash 變量具有全局變量和局部變量之分。其中全局變量可以在任何位置方位到,而局部變量只能在其定義的函數中訪問。
作為演示,看如下 scope.sh 腳本:
#!/bin/bash
v1='A'
v2='B'
myfun() {
local v1='C'
v2='D'
echo "Inside myfun(): v1: $v1, v2: $v2"
}
echo "Before calling myfun(): v1: $v1, v2: $v2"
myfun
echo "After calling myfun(): v1: $v1, v2: $v2"
我們首先定義了兩個全局變量 **v1 和 v2 ,然后在 函數 myfun() 中,使用 local 關鍵字 定義了一個局部變量 ** v1 ,并修改了全局變量 v2 。在不同的函數中,局部變量可以使用相同的變量名。
執行一下,結果如下:
$ ./scope.sh
Before calling myfun(): v1: A, v2: B
Inside myfun(): v1: C, v2: D
After calling myfun(): v1: A, v2: D
由此,我們可以看到:
- 如果局部變量的變量名與全局變量的變量名相同,那么局部變量優先級會更高;
- 在函數中可以更改全局變量的值。
遞歸函數
遞歸函數是一個調用自身的函數。階乘計算是遞歸函數的經典例子,看下面的腳本 factorial.sh:
#!/bin/bash
factorial () {
if [ $1 -le 1 ]; then
echo 1
else
last=$(factorial $(( $1 -1)))
echo $(( $1 * last ))
fi
}
echo -n "4! is: "
factorial 4
echo -n "5! is: "
factorial 5
echo -n "6! is: "
factorial 6
任何遞歸函數都要從一個基本條件開始,這個基本條件必須可以結束遞歸函數調用鏈。在 factorial() 函數中,基本條件為:
if [ $1 -le 1 ]; then
echo 1
然后導出階乘函數的遞歸情況。要計算 n 的階乘,其中 n 是大于 1 的正數,可以將 n 乘以 n-1 的階乘:
factorial(n) = n * factorial(n-1)
使用上面那個公式來編寫遞歸函數的算法:
last=$(factorial $(( $1 -1)))
echo $(( $1 * last ))
然后運行一下,檢查運行結果:
$ ./factorial.sh
4! is: 24
5! is: 120
6! is: 720
-
函數
+關注
關注
3文章
4304瀏覽量
62427 -
腳本
+關注
關注
1文章
387瀏覽量
14830 -
Bash
+關注
關注
0文章
57瀏覽量
10169
發布評論請先 登錄
相關推薦
評論