函数:function
过程式编程:代码重用;
模块化编程;
结构化编程;
把一段独立功能的代码当作一个整体,并为之取一个名字;命名的代码段,此即为函数;
函数的定义和使用:
可在交互式环境下定义函数;
可将函数放在脚本文件中作为它的一部分;
可放在只包含函数的单独文件中;
交互式定义函数:(定义在当前shell环境,重启失效)
#dir() {
> ls-l
> }
#dir #在命令行直接输入函数名dir执行函数;如果函数名与系统命令名字相同,函数优先;
#unset dir #取消函数;
可以将经常使用的函数存入函数文件(函数库),需要调用时将函数文件载入shell;
一旦函数文件载入shell,就可以在命令行或脚本中调用函数;
加载函数库有两种方式:
(1)使用点号:
. /path/to/file.sh
(2)使用source命令:
source /path/to/file
可以使用set命令查看所有已经载入的函数;
若要修改函数,需要先unset取消函数加载,修改后再重新载入shell;
注意:定义函数的代码段不会自动执行,函数只有被调用才会执行;
所谓调用函数,在代码中给定函数名即可;
函数名出现的任何位置,在代码执行时,都会被自动替换为函数代码;
语法一:
function f_name {
函数体
}
语法二:
f_name() {
函数体
}
函数的生命周期:每次被调用时创建,返回时终止;
其状态返回结果为函数体中运行的最后一条命令的状态结果;
自定义状态返回值,需要使用return
return:
0:成功
1-255:失败
给定一个用户名,取得用户的ID号和默认shell;
#vim f1.sh
#/bin/bash
#
userinfo() {
if id "$1" &> /dev/null;then
grep "^$1\>" /etc/passwd | cut -d: -f3,7
else
echo "no this user."
fi
}
userinfo $1
#bash f1.sh root
#bash f1.sh keith
用函数改写服务脚本;
#!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."
else
touch $lockfile
[ $? -eq 0 ] && echo "start $prog finished."
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
函数返回值:
函数的执行结果返回值:
(1)使用echo或printf命令进行输出;
(2)函数体中调用的命令的执行结果;
函数的退出状态码:
(1)默认取决于函数体中执行的最后一条命令的退出状态;
(2)自定义:return;
return命令:
表示从被调函数返回到主调函数继续执行,返回时可自定义一个返回值;
用于函数中,常见用法:returen n; n是一个指定的数字,使函数以指定值退出;如果没有指定n值,则返回值是函数体中执行的最后一个命令的退出状态;
return [n]: Return from a shell function.
vim return.sh
#/bin/bash
function fun_01 { #定义一个函数,该函数简单地返回1;
return 1
}
fun_01 #调用该函数;
echo $? #查看返回值;
#bash return.sh
1
local:声明局部变量;
用于在脚本中声明局部变量,典型的用法是用于函数体内,其作用域在声明该变量的函数体中;
如果试图在函数体外使用local声明变量,会提示错误;
local VAR=value
#vim scope.sh
#!/bin/bash
#
name=tom #本地变量;
setname() {
name=jerry #这里函数会调用本地变量;
echo "Function: $name"
}
setname
echo "Shell: $name"
#bash scope.sh
Function: jerry
Shell: jerry
#vim scope.sh
#!/bin/bash
#
name=tom #本地变量;
setname() {
local name=jerry #局部变量,仅作用于函数体内,不受外部影响;
echo "Function: $name"
}
setname
echo "Shell: $name"
#bash scope.sh
Function: jerry
Shell: tom
函数参数:
函数可以接受参数;
在调用函数时,在函数名后面以空白符分隔给定参数列表即可,例如:testfunc arg1 arg2...;
在函数体当中,可以使用$1,$2...引用传递给函数的参数;还可以在函数中使用$*或$@引用所有参数,$#引用传递的参数的个数;
添加10个用户,添加用户的功能使用函数实现,用户名作为参数传递给函数;
#!/bin/bash
#
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 "unknown error."
fi
done
函数库:
系统自带的函数库: /etc/init.d/functions;
虽然说functions函数库提供了一些好用的函数,但是仅有这些函数是远远不够的,所以自行开发函数库还是日常工作中很重要的部分;
函数递归:
函数调用自身;
阶乘(factorial):
10!=10*9!=10*9*8!=10*9*8*7!=...
n!=n*(n-1)!=n*(n-1)(n-2)!=...
1!=1
0!=1
#vim factorial.sh
#/bin/bash
#
fact() {
if [ $1 -eq 0 -o $1 -eq 1 ];then
echo 1
else
echo $[$1*$(fact $[$1-1])]
fi
}
fact $1
#bash factorial.sh 10
3628800
斐波那契数列(Fibonacci sequence):
1,1,2,3,5,8,13,21,34,...
f(n)=f(n-1)+f(n-2)
#vim fibo.sh
#!/bin/bash
#
fab() {
if [ $1 -eq 1 -o $1 -eq 2 ];then
echo 1
else
echo $[$(fab $[$1-1])+$(fab $[$1-2])]
fi
}
for i in `seq 1 $1`;do
fab $i
done
#bash fibo.sh 7
1
1
2
3
5
8
13
原文地址:http://keithtt.blog.51cto.com/3080111/1813933