一.函数基本知识

        与其他编译语言相比,linux shell 也有函数, 如果脚本中有重复的代码,可以使用函数代替。

1.函数基本形式
 

#!/bin/bash
function  name () {

echo "hello everyone !"

}
name   #调用函数

function 是关键字,可以加可以不加,不影响脚本执行。

name 是函数名,函数内容写好后需要调用它才能生效,函数名在一个脚本内不能相同,否则会被新函数覆盖。

{  } 标记着函数的开始与结尾,括号内是函数内的命令的集合,即是函数体,函数体不允许空命令,至少需要一条。

[root@foundation77 mnt]# vim fun 
[root@foundation77 mnt]# sh fun 
hello everyone !

2.函数调用

 函数之间允许相互调用,或一个函数调用多个函数,调用时,函数不能在定义前使用。

调用函数,计算70到80的平方和立方

[root@foundation77 mnt]# cat fun
#!/bin/bash

function fun1() {                #函数fun1 用于计算方        
    let "squ=i * i"
    echo "square :$squ"
}

function fun2() {                #函数fun2 用于计算立方
     let "c=i * i * i"
     echo "cube :$c"
}
i=70
while [[ "$i" -le "80" ]]
do
  echo "$i "
  fun1                          #脚本中调用函数fun1
  fun2                          # 调用函数fun2
  let "i++"
done
echo "finish"
[root@foundation77 mnt]# sh fun
70 
square :4900
cube :343000
71 
square :5041
cube :357911
72 
square :5184
...
...
80 
square :6400
cube :512000
finish

3.调试脚本

bash -x  脚本名 :可以看到脚本的执行顺序,与每一步的运行结果。每次引用函数时,重新回到函数的定义,调用fun1 时返回至fun1,调用fun2 时返回到fun2.

[root@foundation77 mnt]# bash -x fun 
+ i=70
+ [[ 70 -le 80 ]]
+ echo '70 '
70 
+ fun1
+ let 'squ=i * i'
+ echo 'square :4900'
square :4900
+ fun2
+ let 'c=i * i * i'
+ echo 'cube :343000'
cube :343000
+ let i++
+ [[ 71 -le 80 ]]
+ echo '71 '
71 
+ fun1
+ let 'squ=i * i'
+ echo 'square :5041'
square :5041
+ fun2
+ let 'c=i * i * i'
+ echo 'cube :357911'
cube :357911
+ let i++
+ [[ 72 -le 80 ]]
+ echo '72 '
72 
+ fun1
+ let 'squ=i * i'
...
...
...

4.函数返回值

有时候脚本执行完后需要返回特定的值来完成后续的操作,这些特定的值就是函数的返回值,函数通过return 返回其退出状态,0表示无错误,1表示有错误。

1)编辑脚本,使输入周一到周五的英文翻译

[root@foundation77 mnt]# cat fun
#!/bin/bash
week(){
echo -n "input:"
echo "$1"
case $1 in
0)
  echo "Sunday"
  return 0 
  ;;
1)
  echo "Monday"
  return 0 
  ;;
2) 
 echo "Tuesday"
 return 0
 ;;
3)
 echo "wednesday"
 return 0
 ;;
4)
 echo "Thursday"
 return 0
 ;;
5)
 echo "Friday"
 return 0
 ;;
6)
 echo "saturday"
 return 0
 ;;
*)
 return 1
 ;;
esac
}
if week "$1"
then
  echo "right"
else 
 echo "error"
fi
exit 0

[root@foundation77 mnt]# sh fun 1    
input:1
Monday
right
[root@foundation77 mnt]# sh fun 5
input:5
Friday
right
[root@foundation77 mnt]# sh fun 9
input:9
error
[root@foundation77 mnt]#

2)  将函数运行结果返回给脚本

[root@foundation77 mnt]# vim  fun
#!/bin/bash
function fun1() {
    read -p "Enter a value:" value
    echo "doubling the value..."
    return $[ $value * 2 ]            #返回值的结果
}

fun1

echo "The new value is $?"            #输出函数的返回值


[root@foundation77 mnt]# sh fun
Enter a value:9
doubling the value...
The new value is 18

5.函数作用域

        shell 编程中,变量的存在方式分为局部变量和全局变量。可以通过关键字local 声明局部变量,局部变量将局限在函数范围内,此外,函数也可以调用函数外的全局变量,如果一个局部变量和一个全局变量名字相同,局部变量会覆盖全局变量。

      默认变量为全局变量

 编辑脚本测试变量作用域

[root@foundation77 mnt]# vim fun.sh
#!/bin/bash
function fun1(){
      a=123                      #编辑全局变量a ,赋予初始值为123
      echo $a
}
fun1                             #调用函数fun1
echo $a                          #在函数外输全局变量a

function fun2(){        
     local b=456                 #编辑局部变量b ,赋予初始值456
     echo $b                      
}
fun2   
echo $b                          #在函数外测试是否有输出


[root@foundation77 mnt]# sh fun
123
123
456
                                  #输出为空,不再函数外生效
[root@foundation77 mnt]#

6.函数递归

在shell中可以递归调用函数,意思是函数可以间接调用自身,在递归调用中,主调函数又是被调函数。

1)递归求阶乘

[root@foundation77 mnt]# cat fun.sh 
#!/bin/bash
function jc(){
    local a=$1
if [ "$a" -eq 0 ]
then
 c=1
else
  let "b=a-1"
  jc  $b
  let "c=$a*$?"
fi
return $c
}
jc $1
echo "factorial of $1 is $?"
exit 0
[root@foundation77 mnt]# sh fun.sh 3
factorial of 3 is 6
[root@foundation77 mnt]# sh fun.sh 5
factorial of 5 is 120
[root@foundation77 mnt]# sh fun.sh 8
factorial of 8 is 128                            #?????????

这个脚本在计算较大数值是发生错误,原因是返回值 $?  ,它所能传递的最大值是255,如果计算的阶乘结果大于255就不能使用。