一 函數
函數與shell指令碼沒有明顯區別,但在執行時有本質區別:
對於一個單獨的shell指令碼,執行時為其建立一個新的shell進程,並解釋並執行指令碼中代碼
當指令碼執行完成,該shell進程自動結束
對於函數來說,調用時不會單獨建立一個shell進程,而是在調用者的shell進程中直接解釋並執行函數中的代碼
函數定義:
function_name()
{
statement1
}
(也可以加function關鍵字,函數在調用前必須定義)
例子:
#! /bin/bash
#定義函數
functionsayhello()
{
echo "Hello, World!"
}
#調用函數
sayhello
函數調用:
function_nameparam1 param2
函數連結:
在某個shell函數中調用另外一個函數的過程
例子:
#! /bin/bash
#定義函數john()
john()
{
echo "Hello, this is John."
}
#定義函數alice
alice()
{
#調用函數john
john
echo "Hello, this is Alice."
}
#調用函數alice
alice
結果:Hello, this is John.
Hello,this is Alice.
函數傳回值:
shell可以用return語句來返回某個數值,只能返回0-255直接整數值,函數中的return語句實際上是用來返回函數的退出狀態代碼
例子:
#! /bin/bash
#定義求和函數
sum()
{
let "z = $1 + $2"
#將和作為退出狀態代碼返回
return "$z"
}
#調用求和函數
sum 22 4
#輸出和
echo"$?"
結果:26
(超過255會出錯,如sum 253 4)
設定別名:
alias name=”command”
(name為要指定的名,command為原有shell命令)
函數和別名區別:
使用者不能為一組命令指定別名
別名中不能通過系統變數巨集指令引數列表
不用某個別名時,unalisa name
二 函數參數 2.2 擷取函數參數個數
通過$#來擷取指令碼參數的個數
#! /bin/bash
#定義函數
func()
{
#輸出參數個數
echo "the function has $#parameters."
}
#調用函數
func a b c d e f ghello
func 12 3"hello world"
func
(若參數中有空格,要用引號引起來) 2.2 通過位置變數接收參數值:
$0:指令碼名稱
$1:第一個參數
$2:第二個參數
$@和$*:所有參數
例:
#! /bin/bash
#定義函數
func()
{
#輸出所有的參數hello world
echo "all parameters are $*"
#輸出所有的參數hello world
echo "all parameters are $@"
#輸出指令碼名稱
echo "the script's name is $0"
#輸出第1個參數 hello
echo "the first parameter is $1"
#輸出第2個參數 world
echo "the second paramter is $2"
}
#調用函數
func hello world 2.3 移動位置參數
shift命令使指令碼所有參數左移一個位置
#! /bin/bash
#定義函數
func()
{
#通過while迴圈和shift命令依次擷取參數值,$#擷取傳遞給函數的參數個數
while (($# > 0))
do
#shift命令參數位置左移一個,原來的第二個參數會變成第一個,每次輸出$1就可以了
echo "$1"
shift
done
} 2.4 通過getopts接收函數參數
getopts擷取函數的選項以及參數值,或者是指令碼的命令列選項以及參數值
getopts optstring[args]
參數optstring包含一個可以為getopts命令識別的選項名稱列表。如果某個選項名稱的後面跟隨著一個冒號,則表示使用者可以為該選項提供參數值,同時參數值被儲存到名稱為$OPTARG的系統變數中。
getopts依次遍曆每個選項,選項名稱被儲存到args變數中。
#! /bin/bash
#定義函數
func()
{
#逐個接收選項及其參數
while getopts "a:b:c" arg
do
#當指定了-a選項時
case "$arg" in
a)
#輸出-a選項的參數值
echo "a's argument is$OPTARG"
;;
b)
echo "b's argument is$OPTARG."
;;
c)
echo "c"
;;
?)
#未知選項
echo "unkown argument."
exit 1
;;
esac
done
}
#調用函數
func -a hello -bworld
結果:a's argument is hello
b's argument is world
(a,b後面有冒號,可以含有參數,c不含參數,迴圈過程中,當前選項名稱被儲存到arg中,選項的參數值被儲存到系統變數$OPTARG中。當使用者提供-c選項是,只是簡單輸出字元c) 2.5 間接參數傳遞:
通過間接變數引用來實現函數的參數的傳遞。如果某個變數的值又是另外一個變數的變數名,則該變數稱為間接變數。
var=name
name=john
第二個變數可以用兩種方式引用:
${name}
${!var}
(shell中間接引用文法為${!var_name}) 三 函數庫檔案
指令碼與庫檔案之間的區別在於函數庫檔案只包括函數,指令碼可以即包括函數和變數的定義,又包括執行的代碼。
庫檔案有主程式載入並執行,使用者無需擁有庫檔案的執行許可權,只要讀許可權就可以。 3.1 函數庫檔案的調用
. filename(圓點和檔案名稱之間有空格)
#! /bin/bash
#載入函數庫
. lib.sh
#定義變數
msg="the fileis not found."
#調用函數庫中的函數
error $msg
lib.sh檔案:
#! /bin/bash
#定義函數
error()
{
#1和2都是檔案描述符,1為標誌輸出,2標準錯誤輸出,>&複製一個輸出描述符
echo "ERROR:" $@ 1>&2
}
warning()
{
echo "WARNING:" $@ 1>&2
}
結果:ERROR:the file is not found 3.2 遞迴函式
調用過程就是反覆的調用自己
#! /bin/bash
#定義遞迴函式
fact()
{
#定義局部變數
local n="$1"
#當n等於0時終止遞迴調用
if [ "$n" -eq 0 ]
then
result=1
else
#當n大於0時,遞迴計算n-1的階乘
let "m=n-1"
fact "$m"
let "result=$n * $?"
fi
#將計算結果以退出狀態代碼的形式返回
return $result
}
#調用遞迴函式
fact"$1"
echo"Factorial of $1 is $?"