和大多数编程语言一样,Shell也可以定义和使用函数(function)。Shell函数的本质是一段可以重复使用的脚本代码,这段代码被提前编写好了,放在了指定的位置,使用时直接调取即可。
Shell 函数定义的语法格式如下:
[function] funname [()]{
//语句
command1
command2
command3
[return int]
}
说明:
- Shell的函数定义的时候可以使用
function
关键字,也可以不使用 - funname:函数的名字
- 在每个语句后面可以写上
;
(分号)也可以不写 - Shell的函数没有形参的概念,当需要给函数传参可以使用位置参数进行传参
- return int:参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)
- 函数的返回值使用
$?
获取
函数定义的简化写法
函数定义的时候可以不写function关键字
fun() {
//语句
command1
command2
command3
[return int]
}
如果写了function关键字,可以不写函数名后面的括号(注意这种情况下函数名和{
之间要有空格):
function fun {
//语句
command1
command2
command3
[return int]
}
具体使用哪种方式定义函数,执行的效果没有区别,完全取决于个人喜好!
函数的参数
Shell 中的函数在定义时不能指明参数,但是在调用时却可以传递参数。函数参数是 Shell位置参数的一种,在函数内部可以使用$n
来接收,例如,$1 表示第一个参数,$2 表示第二个参数,依次类推。
除了$n
,还有另外三个比较重要的变量:
$#
可以获取传递的参数的个数;$@
或者$*
可以一次性获取所有的参数。
示例:
#!/bin/bash
function show() {
#获取第一个位置的参数
echo "$1 $2 $3"
echo "$4"
echo "参数个数:$#"
}
#调用函数
show Are you ok "Are you ok?"
执行结果:
函数的调用
Shell 不限制定义和调用的顺序,你可以将定义放在调用的前面,也可以反过来,将定义放在调用的后面。
1、无参函数的调用
调用无参函数,直接在需要的地方写函数名就行了,不需要写括号
#调用函数funname,直接在需要的地方写函数名就行了,不需要写括号
funname
2、有参函数的调用
如果传递参数,那么多个参数之间以空格分隔,函数名字后面都需要带括号:
funname arg1 arg2 arg3.....
案例
在案例中将着重演示使用Shell如何实现递归函数的定义和使用
1、定义一个函数计算n(1<=n<=20)的阶乘
#!/bin/bash
#让用户输入一个[1 20]的数
while true; do
read -p "Input a number: " n
if [ -z "$n" ]; then
printf ""
elif [[ ! ${n} =~ ^[0-9]+$ ]] || [ "$n" -lt 1 -o "$n" -gt 20 ]; then
echo "error number"
else
break
fi
done
#由于Shell的函数返回值最大只能是255,而10!已经大于255了,因为这里不能使用return
#而是应该使用echo输出或者全局变量保存返回值,这里使用全局变量来保存返回值
result=1
function factorial(){
#在函数中可以使用local定义函数本地变量,变量的生命周期只在函数内
local n=$1
if [ $n -eq 1 ]; then
fac=1
else
factorial $[$n-1]
let fac=n*fac
fi
result=$fac
}
#调用函数
factorial $n
echo "The factorial of $n is: " $result
执行结果:
通过这个程序,我们需要了解Shell中递归函数的编写手段以及当函数的返回值超过255了之后我们如何处理。
2、二分查找
写一个脚本实现二分查找
#!/bin/bash
#用户输入一个数组,要求数组元素必须全部是数字
j=0
for i in $@; do
array[j++]=$i
done
read -p "Input a number you want to search: " num
function binarySearch(){
array=$1
key=$2
head=0
tail=$[${#array[@]}-1]
while [ ${head} -le ${tail} ]; do
let mid=(head+tail)/2
if [ "${array[$mid]}" -eq "$key" ]; then
echo "index of ${key} is $mid"
break
elif [ "${array[$mid]}" -gt "$key" ]; then
let tail=mid-1
else
let head=mid+1
fi
done
}
result=`binarySearch "${array[*]}" $num`
if [ -z "$result" ]; then
echo "Not find key: $num"
else
echo $result
fi
执行结果: