shell脚本编程-函数

一、函数的定义和调用

二、函数的返回值

三、带参数的函数

四、自定义函数库

五、functions函数库

六、递归函数

一、函数的定义和调用

  函数是Shell脚本中自定义的一系列执行命令,一般来说函数应该设置返回值.

  语法:

#shell中的函数定义
#其中function为关键字,FUNCTION_NAME为函数名
funciton FUNCTON_NAME(){
  command1 #函数体中可以有多个语句,不允许有空语句
  command2
  ...
}
#省略关键字function,效果一样
FUNCTION_NAME(){
  command1
  command2
  ...
}

  eg:

 1 [rhat@localhost shell]$ vim sayHello.sh
 2 #!/bin/bash
 3 function sayHello(){
 4     echo "Hello"
 5 }
 6 echo "Call function sayHello"
 7 sayHello
 8 [rhat@localhost shell]$ sh ./sayHello.sh 
 9 Call function sayHello
10 Hello

  or

 1 [rhat@localhost shell]$ vim countLine.sh
 2 #!/bin/bash
 3 FILE=/etc/passwd
 4 function countLine(){
 5     local i=0
 6     while read line
 7     do
 8         let ++i
 9     done < $FILE
10     echo "$FILE have $i lines"
11 }
12 echo "Call function countLine"
13 countLine
14 #执行结果
15 [rhat@localhost shell]$ sh ./countLine.sh 
16 Call function countLine
17 /etc/passwd have 31 lines

 二、函数的返回值

  函数的返回值又叫函数的返回状态,实际上是一种通信方式.获取上一个命令返回值得方式是使用$?

  eg:

 1 [rhat@localhost shell]$ vim checkFileExist.sh
 2 #!/bin/bash
 3 FILE=/etc/notExistFile
 4 function checkFileExist(){
 5     if [ -f $FILE ];then
 6         return 0
 7     else
 8         return 1
 9     fi
10 }
11 echo "Call function checkFileExist"
12 checkFileExist    #调用函数
13 if [ $? -eq 0 ];then
14     echo "$FILE exist"
15 else
16     echo "$FILE not exist"
17 fi
18 #执行结果
19 [rhat@localhost shell]$ sh ./checkFileExist.sh 
20 Call function checkFileExist
21 /etc/notExistFile not exist

  or

 1 [rhat@localhost shell]$ vim checkNum.sh 
 2 #!/bin/bash
 3 function checkNum(){
 4     echo -n "Please input a number:"
 5     read NUM
 6     if [ $NUM -ge 0 -a $NUM -lt 10 ];then
 7         return 0
 8     fi
 9     if [ $NUM -ge 10 -a $NUM -lt 20 ];then
10         return 1
11     fi
12     if [ $NUM -ge 20 -a $NUM -lt 30 ];then
13         return 2
14     fi
15     return 3
16 }
17 echo "Call function checkNum"
18 checkNum
19 RTV=$?
20 if [ $RTV -eq 0 ];then
21     echo "The number is between[0,10]"
22 elif [ $RTV -eq 1 ];then
23     echo "The number is between[10,20]"
24 elif [ $RTV -eq 2 ];then
25     echo "The number is between[20,30]"
26 else
27     echo "Unknown input"
28 fi
29 #执行结果
30 [rhat@localhost shell]$ sh ./checkNum.sh 
31 Call function checkNum
32 Please input a number:30
33 Unknown input

三、带参数的函数

  向函数传递参数是使用位置参数来实现的.

 1 [rhat@localhost shell]$ vim checkFileExist_v2.sh 
 2 #!/bin/bash
 3 function checkFileExist(){
 4     if [ -f $1 ];then
 5         return 0
 6     else
 7         return 1
 8     fi
 9 }
10 echo "Call function checkFileExist"
11 checkFileExist $1
12 if [ $? -eq 0 ];then
13     echo "$FILE exist"
14 else
15     echo "$FILE not exist"
16 fi
17 #执行结果.
18 [rhat@localhost shell]$ sh ./checkFileExist_v2.sh haha.txt
19 Call function checkFileExist
20  not exist

  or

 1 [rhat@localhost shell]$ vim power.sh
 2 #!/bin/bash
 3 function power(){
 4     RESULT=1
 5     LOOP=0
 6     while [[ "$LOOP" -lt $2  ]]
 7     do
 8         let "RESULT=RESULT*$1"
 9         let "LOOP+=1"
10     done
11     echo $RESULT
12 }
13 echo "Call function power with parameters"
14 power $1 $2
15 #执行结果
16 [rhat@localhost shell]$ sh ./power.sh 3 3
17 Call function power with parameters
18 27

  除了在脚本运行时给脚本传入位置参数外,还可以使用内置命令set命令给脚本指定位置参数的值.(又叫重置)

 1 [rhat@localhost shell]$ vim set01.sh 
 2 #!/bin/bash
 3 set 1 2 3 4 5 6
 4 COUNT=1
 5 for i in $@
 6 do 
 7     echo "Here \$$COUNT is $i"
 8     let "count++"
 9 done
10 #执行结果
11 [rhat@localhost shell]$ sh ./set01.sh a b c d e f 
12 Here $1 is 1
13 Here $1 is 2
14 Here $1 is 3
15 Here $1 is 4
16 Here $1 is 5
17 Here $1 is 6

  在shell中使用shift命令移动位置参数.shift命令可以让位置参数左移一位.

 1 [rhat@localhost shell]$ vim shift03.sh
 2 #!/bin/bash
 3 until [ $# -eq 0 ]
 4 do
 5     echo "Now \$i is :$1,total parameter is:$#"
 6     shift #加数字 2 表示 左移2个参数,eg: shift 2
 7 done
 8 #执行结果
 9 [rhat@localhost shell]$ sh ./shift03.sh 1 2 3 a v c
10 Now $i is :1,total parameter is:6
11 Now $i is :2,total parameter is:5
12 Now $i is :3,total parameter is:4
13 Now $i is :a,total parameter is:3
14 Now $i is :v,total parameter is:2
15 Now $i is :c,total parameter is:1

四、自定义函数库

  对某些很常用的功能,必须考虑将其独立出来,集中存放在一些独立的文件中,这些文件就称为”文件库“,在实践中建议库函数使用下划线开头.

  eg:lib01.sh 函数库.

1 [rhat@localhost shell]$ vim lib01.sh
2 _checkFileExist(){
3     if [ -f $1 ];then
4         echo "File:$1 exist"
5     else
6         echo "File:$1 not exist"
7 }

  加载函数库的两种方式:

1 #使用”点“.命令。
2 [rhat@localhost shell]$ . ./lib01.sh      # / 前面的.表示当前目录,,别搞混。
3 #使用source命令。
4 [rhat@localhost shell]$ source ./lib01.sh 

  脚本中调用函数库.

1 [rhat@localhost shell]$ vim callLib01.sh
2 #!/bin/bash    
3 source ./lib01.sh            #引用函数库到当前shell.
4 _checkFileExist /etc/notExistFile
5 _checkFileExist /etc/passwd
6 #执行结果
7 [rhat@localhost shell]$ sh ./callLib01.sh 
8 File:/etc/notExistFile not exist
9 File:/etc/passwd exist

五、函数库/etc/init.d/functions简介

  很多Linux发行版中都有/etc/init.d目录,这是系统中放置所有开机启动脚本的目录,这些开机脚本在脚本开始运行时都会加载/etc/init.d/functions 或/etc/rc.d/init.d/functionshanshuku.(两个库内容实际上完全一样. 如下:

1 # Source functions library
2  . /etc/init.d/functions
3 或者
4 # Source functions library
5 . /etc/rc.d/init.d/functions

  在脚本中使用functions函数库.

 1 [rhat@localhost shell]$ vim callFunctions01.sh
 2 #!/bin/bash
 3 source /etc/init.d/functions
 4 confirm ITEM    #confirm 实际上是functions库中的一个函数功能.
 5 if [[ $? -eq 0 ]];then
 6     echo "ITEM confirmed"
 7 else
 8     echo "ITEM not confirmed"
 9 fi
10 #执行结果.
11 [rhat@localhost shell]$ sh ./callFunctions01.sh 
12 Start service ITEM (Y)es/(N)o/(C)ontinue? [Y] y
13 ITEM confirmed

  functions库中常用的函数:

checkpid() 检查某个PID是否存在
daemon() 以deamon方式启动某个服务
killproc() 停止某个进程
pidfileofproc() 检查某个进程的PID文件
pidofproc() 检查某个进程的PID
status() 判断某个服务的状态
echo_success() 打印OK
echo_failure() 打印FAILED
echo_passed() 打印PASSED
echo_warning() 打印WARNING
success() 打印OK并记录日志
failure() 打印FAILED并记录日志
passed() 打印PASSED并记录日志
warning() 打印WARNING并记录日志
action() 执行给定的命令,并根据执行结果打印信息
strstr() 检查$1字符串中是否含有$2字符串
confirm() 提示是否启动某个服务.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 六、递归函数

  在函数中继续调用函数自身,注意调用条件,否则会毫无止境的调用,语法:

function recursion(){
        recursion
        confitionThatEndTheRecursion    #停止递归的条件.
}

  例如阶乘函数:n!=1x2x3x4x...xn.

 1 [rhat@localhost shell]$ cat factorial01.sh 
 2 #!/bin/bash
 3 function factorial01(){
 4     local NUMBER=$1
 5     if [ $NUMBER -le 0 ];then
 6         RES=1
 7     else
 8         factorial01 $((NUMBER-1))
 9         TEMP=$RES
10         NUMBER=$NUMBER
11         RES=$((NUMBER*TEMP))
12     fi
13 }
14 factorial01 $1
15 echo $RES
16 #执行结果
17 [rhat@localhost shell]$ sh -x ./factorial01.sh 4 #-x为观察执行过程的细节.
18 + factorial01 4
19 + local NUMBER=4
20 + '[' 4 -le 0 ']'
21 + factorial01 3
22 + local NUMBER=3
23 + '[' 3 -le 0 ']'
24 + factorial01 2
25 + local NUMBER=2
26 + '[' 2 -le 0 ']'
27 + factorial01 1
28 + local NUMBER=1
29 + '[' 1 -le 0 ']'
30 + factorial01 0
31 + local NUMBER=0
32 + '[' 0 -le 0 ']'
33 + RES=1
34 + TEMP=1
35 + NUMBER=1
36 + RES=1
37 + TEMP=1
38 + NUMBER=2
39 + RES=2
40 + TEMP=2
41 + NUMBER=3
42 + RES=6
43 + TEMP=6
44 + NUMBER=4
45 + RES=24
46 + echo 24
47 24

  linux shell 汉诺塔实现:我没理解得了.((~﹃~)~zZ)

 1 [rhat@localhost shell]$ vim hanoi01.sh
 2 #!/bin/bash
 3 function hanoi01(){
 4     local num=$1
 5     if [ "$num" -eq "1" ]; then
 6         echo "Move:$2---->$4"
 7     else
 8         hanoi01 $((num-1)) $2 $4 $3
 9         echo "Move:$2---->$4"
10         hanoi01 $((num-1)) $3 $2 $4
11     fi
12 }
13 hanoi01 4 A B C
14 #执行结果
15 [rhat@localhost shell]$ sh ./hanoi01.sh 
16 Move:A---->B
17 Move:A---->C
18 Move:B---->C
19 Move:A---->B
20 Move:C---->A
21 Move:C---->B
22 Move:A---->B
23 Move:A---->C
24 Move:B---->C
25 Move:B---->A
26 Move:C---->A
27 Move:B---->C
28 Move:A---->B
29 Move:A---->C
30 Move:B---->C

  嵌套函数天生的结构就注定了其晦涩的可读性,在不少大公司内部的开发规范中也明确规定了不允许使用递归,所以在实际工作中药尽量避免使用递归.

返回顶部

posted @ 2015-09-27 18:19  超超xc  Views(608)  Comments(0Edit  收藏  举报
I suppose,were childrenonec.