函数:function,过程式编程,可用来实现代码重用;函数能实现2种功能,模块化编程、结构化编程;
把一段独立功能的代码当做一个整体,并为之取一个名字;命名的代码段即为函数;
定义函数的代码段不会自动执行,在调用时才执行;
调用函数时,在代码中给定函数名即可;
函数名出现的任何位置,在代码执行时都会被自动替换为函数代码;
1、函数的语法结构
语法一:
function f_name {
函数体
}
语法二:
f_name() {
函数体
}
2、函数的生命周期:每次被调用时创建,返回时终止;
函数的状态返回结果为函数体中运行的最后一条命令的状态结果;
自定义状态返回值,需使用’return’命令;取值范围[0-255];’0’表示成功,非’0’表示失败;
示例理解1:给定一个用户名,取得用户的ID号和默认shell;
#!/bin/bash
#
userinfo() {
if id "$username" &> /dev/null; then
grep "^$username\>" /etc/passwd | cut -d: -f3,7
else
echo "no such user."
fi
}
username=$1
userinfo
username=$2
userinfo
#后面的2个userinfo 表示调用前面定义的函数;
示例理解2:传递参数;
#!/bin/bash
#
lockfile=/var/lock/subsys/$0
if [ $# -lt 1 -o $# -gt 1 ]; then
echo "$0 's arg : {start|stop|restart|status}."
exit 22
fi
b_name=$(basename $0)
blockfile=/var/lock/subsys/$b_name
start() {
if [ -f $lockfile ]; then
echo "file is already exitses. it is started."
else
touch $lockfile
[ $? -eq 0 ] && echo "start:file is created."
fi
}
stop() {
if [ -f $lockfile ]; then
rm -rf $lockfile
[ $? -eq 0 ] && echo "stop:file is delete."
else
echo "it is already stop."
fi
}
status() {
if [ -f $lockfile ]; then
echo "running : start status."
else
echo "stopped : stop status."
fi
}
us_age() {
echo "$0 's arg : {start|stop|status|restart}"
echo "quit"
exit 11
}
case $1 in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
status
;;
*)
us_age
exit 11
;;
esac
3、函数返回值
函数的执行结果返回值:
1> 使用echo或printf命令进行输出;
2> 函数体中调用的命令的执行结果;
函数的退出状态码:
1> 默认取决于函数体中执行的最后一条命令的退出状态码;
2> 自定义:return;
4、函数可以接受参数
函数在被调用的时候,可以传递参数给函数:
在函数体中,可以使用位置变量”$1,$2…”,引用这些位置变量给函数传递参数;
还可以在函数体中使用”$*或者$@”,表示引用所有参数,”$#”表示引用传递的参数的个数(数字);
在调用函数时,在函数名后面以空白字符为分隔,后接具体的参数值列表,分别对应函数体中的各个位置变量;
所以,函数体中使用的位置变量与传递给脚本的位置变量不是同一概念!!!!
示例理解3:添加10个用户,使用函数功能实现;用户名当做函数的参数值传递给函数;
if [ $# -lt 1 -o $# -ge 2 ]; then
echo "usage: $b_name arg is singel one."
exit 11
fi
add_user() {
if id $1 &> /dev/null; then
return 5
else
useradd $1
retval1=$?
return=$retval1
fi
}
b_name=$(basename $0)
for i in {1..10}; do
add_user ${1}${i}
retval2=$?
if [ $retval2 -eq 0 ]; then
echo "add user ${1}${i} finished."
elif [ $retval2 -eq 5 ]; then
echo "user ${1}${i} exists."
else
echo "unknow error."
fi
done
示例理解4: 使用函数功能实现ping一个主机来测试主机在线状态;主机地址通过参数传递给函数
#!/bin/bash
#
declare -i i=1
declare -i up_hosts=0
declare -i down_hosts=0
p2_ing() {
ping -W 1 -c 1 $1 &> /dev/null
sub_return=$?
if [ $sub_return -eq 0 ]; then
echo "$1 is UP."
return 0
else
echo "$1 is DOWN."
return 4
fi
}
while [ $i -le 67 ]; do
p2_ing 172.16.$i.1
[ $? -eq 0 ] && let up_hosts++ || let down_hosts++
let i++
done
echo "UP hosts is $up_hosts ; DOWN hosts is $down_hosts."
p2_ing() {
ping -c 5 $1 &> /dev/null
sub_return=$?
if [ $sub_return -eq 0 ]; then
return 0
else
return 4
fi
}
declare -i i=1
declare -i up_hosts=0
declare -i down_hosts=0
while [ $i -le 67 ]; do
h_ost=172.16.$i.1
p2_ing $h_ost
sub2_return=$?
if [ $sub2_return -eq 0 ]; then
echo "$h_ost alive."
let up_hosts+=1
elif [ $sub2_return -eq 4 ]; then
echo "$h_ost dead."
let down_hosts+=1
else
echo "unknow error."
fi
let i++
done
echo "UP hosts is $up_hosts ; DOWN hosts is $down_hosts."
示例理解5:打印NN乘法表; 向脚本传递一个数字(正整数);
#!/bin/bash
#
multi_tab() {
echo -e -n "${1}x${2}=$[${1}*${2}]\t"
}
declare -i i=1
while [ $i -le $1 ]; do
declare -i j=1
while [ $j -le $i ]; do
multi_tab $j $i
let j++
done
let i++
echo
done
5、函数的变量的作用域
函数的变量属于局部变量;
局部变量的作用域:在函数被调用结束时会被自动销毁;
定义局部变量的方法:local VARIABLE=VALUE
本地变量的作用域:运行脚本的shell进程的生命周期,作用范围是当前shell脚本程序文件;
局部变量可以引用本地变量,如果不想让局部变量引用本地变量,可手动定义局部变量;
示例理解6:本地变量与局部变量的作用域;
#!/bin/bash
#
name=lucifer
set_name() {
name=fitz
echo "Function:$name."
}
set_name
echo "shell:$name"
#脚本执行结果:
[root@KOU abc]#
[root@KOU abc]# bash 9.sh
Function:fitz.
shell:fitz
[root@KOU abc]#
#!/bin/bash
#
name=lucifer
set_name() {
local name=fitz
echo "Function:$name."
}
set_name
echo "shell:$name"
#脚本执行结果:
[root@KOU abc]#
[root@KOU abc]# bash 9.sh
Function:fitz.
shell:lucifer
[root@KOU abc]#
==================================== 以下开启烧脑模式 =====================================
6、函数递归
阶乘: 传递一个正整数给脚本;
10!=10*9!=10*9*8!=10*9*8*7!=10*9*8*7*6!=…
#!/bin/bash
#
fact() {
if [ $1 -eq 0 -o $1 -eq 1 ]; then
echo 1
else
echo $[$1*$(fact $[$1-1])]
fi
}
fact $1
运算过程: 以传递参数为'4',观看运算过程; + fact 4 + '[' 4 -eq 0 -o 4 -eq 1 ']' ++ fact 3 ++ '[' 3 -eq 0 -o 3 -eq 1 ']' +++ fact 2 +++ '[' 2 -eq 0 -o 2 -eq 1 ']' ++++ fact 1 ++++ '[' 1 -eq 0 -o 1 -eq 1 ']' ++++ echo 1 +++ echo 2 ++ echo 6 + echo 24 24
斐波那契数列:
1 1 2 3 5 8 13 21 34 55 89 144 233 …
从第三项开始,每个数字都是前2位数字之和;
#!/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