shell 编程之函数
简介
把一段独立功能的代码当作一个整体,并为之一个名字;命名的代码段,此即为函数。函数存在的意义,就是为了可以更加方便地进行代码重用。
函数不会自动执行,只有在代码中调用函数名称,才会在调用位置执行函数所包含的代码段。
shell 编程的函数有两种语法:
# 语法一:
function f_name {
...函数体...
}
# 语法二:
f_name() {
...函数体...
}
返回值与返回状态
函数的返回值,即函数内代码段执行的输出结果,比如:
test_fuc() {
echo 123
}
test_fuc
则此函数的返回值,就是 123
。
函数的返回状态,即函数体中运行的最后一条命令的状态结果,也可以使用 return
进行自定义返回状态。
test_fuc() {
id hzz
return_id=$?
return $return_id
}
test_fuc
echo $?
执行到 return 后,函数会中断并退出,且返回 return 后面所跟的状态值。
接收参数
函数可以使用脚本中定义的变量,也可以接收脚本提供的参数。
# 直接使用脚本变量
iname=hzz
id_name() {
id $iname
}
id_name
# 接收脚本参数
iname=hzz
id_name() {
id $1
}
id_name $iname
注意:函数体内所获取的 $1
,不是脚本的 $1
参数,而是脚本传递给函数体的 $1
参数,其他传参类似。其实可以将整个函数体看做是一个完整的脚本,引用函数可看做是调用并执行脚本文件。
局部变量
在 shell 脚本中,直接定义的变量只在脚本中生效。同样的,在函数中,也可以并且推荐使用 local 定义局部变量,使得变量只在函数中生效。
函数内部尽量使用局部变量,以免跟主程序冲突。除非此函数的备份功能是为了改变主程序的变量。
iname=hzz
id_name() {
local iname=xyz
echo $iname
}
id_name
echo $iname
从执行结果可以看到,iname 并没有被函数改变,因为函数定义的是局部变量。
函数递归
函数递归,即函数直接或间接调用其本身。要小心使用,避免造成死循环。
test_fuc() {
iname=$1
if [[ "$iname" == "hzz" ]]; then
echo right
iname=xyz
test_fuc $iname
else
echo wrong
return 1
fi
}
test_fuc hzz
示例
服务脚本框架
#!/bin/bash
#
# chkconfig: - 50 50
# description: test service script
#
prog=$(basename $0)
lockfile=/var/lock/subsys/$prog
start() {
if [ -f $lockfile ]; then
echo "$prog is running yet."
else
touch $lockfile
[ $? -eq 0 ] && echo "start $prog finshed."
fi
}
stop() {
if [ -f $lockfile ]; then
rm -f $lockfile
[ $? -eq 0 ] && echo "stop $prog finished."
else
echo "$prog is not running."
fi
}
status() {
if [ -f $lockfile ]; then
echo "$prog is running"
else
echo "$prog is stopped."
fi
}
usage() {
echo "Usage: $prog {start|stop|restart|status}"
}
case $1 in
start)
start ;;
stop)
stop ;;
restart)
stop
start ;;
status)
status ;;
*)
usage
exit 1 ;;
esac
根据参数创建10个用户
#!/bin/bash
#
# 5: user exists
addusers() {
if id $1 &> /dev/null; then
return 5
else
useradd $1
retval=$?
return $retval
fi
}
for i in {1..10}; do
addusers ${1}${i}
retval=$?
if [ $retval -eq 0 ]; then
echo "Add user ${1}${i} finished."
elif [ $retval -eq 5 ]; then
echo "user ${1}${i} exists."
else
echo "Unkown Error."
fi
done
计算 N! 运算
#!/bin/bash
#
fact() {
if [ $1 -eq 0 -o $1 -eq 1 ]; then
echo 1
else
echo $[$1*$(fact $[$1-1])]
fi
}
fact $1
序列
1,1,2,3,5,8...
后一个数是前面的数字之和。
#!/bin/bash
#
fab() {
if [ $1 -eq 1 ]; then
echo -n "1 "
elif [ $1 -eq 2 ]; then
echo -n "1 "
else
echo -n "$[$(fab $[$1-1])+$(fab $[$1-2])] "
fi
}
for i in $(seq 1 $1); do
fab $i
done
echo
打印 NN 乘法表
#!/bin/bash
#
max=$1
m_table() {
local max=$max
for ((i=1;i<=$max;i++)); do
for ((j=1;j<=$i;j++)); do
echo -n "$j*$i=$[$i*$j] "
done
echo
done
}
m_table