1. 定义和使用函数
定义函数的格式:
name ()
{
command-list;
}
调用函数的格式:
name #省略括号
2. 检查函数定义和取消函数定义
查看到所声明的函数定义:
declare –f name
取消定义的函数,可以使用unset命令:
unset name
3. 参数和返回数据
案例:
#!/bin/bash
#定义函数printMsg用来输出信息到终端屏幕,该函数至少需要两个参数
printMsg()
{
#如果参数个数小于两个,打印错误信息并且退出状态为1
if [ $# -lt 2 ]
then
echo "printMsg() need 2 or more arguments..."
#使用return语句退出函数的执行,并制定退出状态
return 1
fi
#保存第一个参数值
PREFIX="$1"
#在参数列表中去除第一个参数
shift
#以参数1、参数2、参数3、参数4的形式打印出参数列表
echo "$PREFIX:$@"
#函数执行到这里会以最后一个命令的退出状态退出
}
#定义函数logMsg用来记录信息到log文件,该函数至少可以接收一个参数
logMsg()
{
#判断是否制定了参数的另一种方式,查看第一个参数是否为空
if [ -n "$1" ]
then
#如果参数不为空,把日期和参数列表输出到log文件中
echo "`date` $@" >> ./arguments.log
else
#如果参数为空,输出错误信息并让函数以退出状态1返回
echo "logMsg() needs some arguments."
return 1
fi
}
#通过两个参数调用函数printMsg,如果函数以非零值退出,才会调用logMsg函数
#由于指定了足够的参数,printMsg函数会返回成功值0,所以logMsg不会被调用
printMsg "From printMsg()" "it works..." "aabbcc" && logMsg "From logMsg()" "it works...."
注意:
1 如果定义的函数名与bash内建的命令相同,则这个函数会覆盖内建命令。
4. 变量的作用域
本地变量:在函数内部所定义的变量只能在函数内部使用。变量前加了local。
全局变量:可以在脚本内任何地方使用。
解读:为了程序不混乱,尽量使用本地变量,命名更具有描述性。
5. 递归调用
递归调用:函数调用本身。
案例:
#!/bin/bash
#定义计算阶乘的函数recursive,它接收一个参数
recursive()
{
#如果指定的参数为数字1,则直接返回结果1
if [ $1 - eq 1 ]
then
echo "1"
#函数以状态0返回
return 0
fi
#定义本地变量TEMP,其中保存了参数值减1后的值
local TEMP=`expr $1 -1`
#在recursive的函数体内递归调用函数recursive本身
#指定变量TEMP作为调用函数的参数
#使用命令替换的方式调用函数,就像执行一个普通命令一样
local PREVIOUS=`recursive $TEMP`
#把数值($1减1)的阶乘计算结果和参数值$1相乘
#特殊字符星号*需要被引用,才能正确地传递给expr命令
RESULT=`expr $1 \* $PREVIOUS`
#输出数值$1的阶乘计算结果
echo $RESULT
#退出状态0表示计算成功
return 0
}
#提示用户输入整数值做阶乘运算,数值小于20是为了防止计算结果超出变量存储范围
echo
echo -n " Enter a number (<20) to do n! operation (type "quit" to exit): "
read INPUT
#当用户输入字符串quit时,until循环结束,脚本退出
until [ "$INPUT" = "quit" ]
do
#对输入数据进行匹配
case $INPUT in
#合法的输入可以是1到9的个位数,或者是10到19的两位数,还可以是20
[1-9]|[1][0-9]|20)
#调用递归函数并保存计算结果
OUTCOME=`recursive "$INPUT"`
echo " After computing,$INPUT!=$OUTCOME"
echo
;;
#对所有不合法的输入进行匹配
*)
echo
echo " Not a valid number,Enter again!"
;;
esac
#为下一次阶乘运算读取用户输入的数据
echo -n " Enter a number(<20) to do n!operation (type "quit" to exit):"
read INPUT
done
echo
echo " Bye."
exit 0
6. 函数库
函数库:指的是将通用的函数先定义好一个脚本,方便其他脚本调用。
注意:
1 不要以#!/bin/bash开始库文件,同时给库文件添加可执行权限
2 要在脚本文件的一开始执行库文件
案例:
库文件:
#!/bin/echo Warning:this is a library which should be sourced!
#上面一行的作用是防止库文件被意外执行
#定义函数test_platform用来测试当前的操作系统
test_platform(){
#在本地变量osname中保存当前的操作系统
local osname=`uname -s`
#定义全局变量PLATFORM,并初始化为UNKOWN
PLATFORM=UNKNOWN
#根据当前的操作系统指定变量PLATFORM的值
case ${osname} in
"FreeBSD" in
PLATFORM="FREEBSD"
;;
"SunOS"
PLATFORM="SUNOS"
;;
"Linux"
PLATFORM="LINUX"
;;
esac
return 0
}
脚本:
#!/bin/bash
#首先在脚本程序中包含进库文件library.lib从而可以调用其中定义的函数
source ./library.lib
#调用函数库中的函数test_platform
test_platform
#输出函数test_platform中定义的全局变量PLATFORM
echo
echo "Our running platform is $PLATFORM"
exit 0