函数:代码复用 模块编程
语法:
function f_name { 函数体 } f_name() { 函数体 }
调用:使用函数名
函数名出现的地方,会被自动替换为函数代码;
练习:利用函数改写此前的服务脚本:
#!/bin/bash # prog=`basename $0` lockfile=/var/lock/subsys/$prog start() { if [ -e $lockfile ]; then echo "$prog is already running." else touch $lockfile [ $? -eq 0 ] && echo "Starting $prog finished." fi } stop() { if [ -e $lockfile ]; then rm -f $lockfile [ $? -eq 0 ] && echo "Stoping $prog finished." else echo "$prog is stopped yet." fi } case $1 in "start") start ;; "stop") stop ;; "restart") stop start ;; *) echo "Usage: $prog {start|stop|restart}" exit 1 esac
函数的返回值:
函数的执行结果返回值:
函数中使用打印语句:echo, printf
函数体中OS命令执行结果的输出
函数的退出状态码:
默认取决于函数体执行的最后一个命令的退出状态码;
自定义退出状态码:
return [0-255]
注意:函数体运行时,一旦遇到return语句,函数即返回;
函数可接受参数:
传递参数给函数:调用函数时,在函数名后给出参数列表即可;例如“testfunc arg1 arg2 arg3”
在函数体中可使用$1, $2,...来调用传递过来的各参数;
可使用类似脚本的特殊变量:
$*, $@: 一次性获取参数列表:
$#: 参数的个数
#!/bin/bash # showuserinfo() { [ $# -lt 1 ] && return 1 ! id $1 &> /dev/null && return 2 grep "^$1\>" /etc/passwd | cut -d: -f7 [ $? -eq 0 ] && return 0 || return 3 } while true; do read -p "Enter a username: " username [ "$username" == 'quit' ] && break showuserinfo $username [ $? -ne 0 ] && echo "There is something wrong." done
练习:写一个脚本,完成如下功能(使用函数):
1、提示用户输入一个可执行命令;
2、获取这个命令所依赖的所有库文件(使用ldd命令);
3、复制命令至/mnt/sysroot/对应的目录中
解释:假设,如果复制的是cat命令,其可执行程序的路径是/bin/cat,那么就要将/bin/cat复制到/mnt/sysroot/bin/目录中,如果复制的是useradd命令,而useradd的可执行文件路径为/usr/sbin/useradd,那么就要将其复制到/mnt/sysroot/usr/sbin/目录中;
4、复制各库文件至/mnt/sysroot/对应的目录中;
#!/bin/bash # target=/mnt/sysroot [ -d $target ] || mkdir $target preCmd() { if which $1 &> /dev/null; then cmdpath=$(which --skip-alias $1) return 0 else echo "No such command." return 1 fi } cmdCopy() { cmddir=$(dirname $cmdpath) [ -d $target/$cmddir ] || mkdir -p $target/$cmddir [ -f $target/$cmdpath ] || cp $1 $target/$cmddir return 0 } libCopy() { for lib in $(ldd $1 | grep -E -o "/[^[space::]]+"); do libdir=$(dirname $lib) [ -d $target/$libdir ] || mkdir -p $target/$libdir [ -f $target/$lib ] || cp $lib $target/$libdir done return 0 } main() { while true; do read -p "Plz enter a command(quit): " cmd [ "$cmd" == 'quit' ] && break preCmd $cmd if [ $? -eq 0 ]; then cmdCopy $cmdpath libCopy $cmdpath fi done } main
函数递归:
函数直接或间接调用函数自身;
1 1 2 3 5 8 13
阶乘:10!
n(n-1)!
n(n-1)(n-2)!
阶乘函数:
fact() { if [ $1 -eq 0 -o $1 -eq 1 ]; then echo 1 else echo $[$1*$(fact $[$1-1])] fi }