Shell教程—Shell函数

和大多数编程语言一样,Shell也可以定义和使用函数(function)。Shell函数的本质是一段可以重复使用的脚本代码,这段代码被提前编写好了,放在了指定的位置,使用时直接调取即可。

Shell 函数定义的语法格式如下:

[function] funname [()]{
      //语句
      command1
      command2
      command3
      [return int]
}

说明:

  • Shell的函数定义的时候可以使用function关键字,也可以不使用
  • funname:函数的名字
  • 在每个语句后面可以写上;(分号)也可以不写
  • Shell的函数没有形参的概念,当需要给函数传参可以使用位置参数进行传参
  • return int:参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)
  • 函数的返回值使用$?获取

函数定义的简化写法

函数定义的时候可以不写function关键字

fun() {
  //语句
  command1
  command2
  command3
  [return int]  
}

如果写了function关键字,可以不写函数名后面的括号(注意这种情况下函数名和{之间要有空格):

function fun {
   //语句
   command1
   command2
   command3
   [return int]  
}

具体使用哪种方式定义函数,执行的效果没有区别,完全取决于个人喜好!

函数的参数

Shell 中的函数在定义时不能指明参数,但是在调用时却可以传递参数。函数参数是 Shell位置参数的一种,在函数内部可以使用$n来接收,例如,$1 表示第一个参数,​$2 表示第二个参数,依次类推。

除了$n,还有另外三个比较重要的变量:

  • $#可以获取传递的参数的个数;
  • $@或者$*可以一次性获取所有的参数。

示例:

#!/bin/bash
function show() {
   #获取第一个位置的参数
   echo "$1 $2 $3"
   echo "$4"
   echo "参数个数:$#"
}

#调用函数
show Are you ok "Are you ok?"

执行结果:

函数的调用

Shell 不限制定义和调用的顺序,你可以将定义放在调用的前面,也可以反过来,将定义放在调用的后面。

1、无参函数的调用

调用无参函数,直接在需要的地方写函数名就行了,不需要写括号

#调用函数funname,直接在需要的地方写函数名就行了,不需要写括号
funname
2、有参函数的调用

如果传递参数,那么多个参数之间以空格分隔,函数名字后面都需要带括号:

funname arg1 arg2 arg3.....

案例

在案例中将着重演示使用Shell如何实现递归函数的定义和使用

1、定义一个函数计算n(1<=n<=20)的阶乘
#!/bin/bash

#让用户输入一个[1 20]的数
while true; do
  read -p "Input a number: " n
  if [ -z "$n" ]; then
     printf ""
  elif [[ ! ${n} =~ ^[0-9]+$ ]]  || [ "$n" -lt 1 -o "$n" -gt 20  ]; then
     echo "error number"
  else
     break
  fi
done

#由于Shell的函数返回值最大只能是255,而10!已经大于255了,因为这里不能使用return
#而是应该使用echo输出或者全局变量保存返回值,这里使用全局变量来保存返回值
result=1

function factorial(){
    #在函数中可以使用local定义函数本地变量,变量的生命周期只在函数内
    local n=$1
    if [ $n -eq 1  ]; then
        fac=1
     else
       factorial $[$n-1]
       let fac=n*fac
     fi
     result=$fac
}

#调用函数
factorial $n

echo "The factorial of $n is: " $result

执行结果:

通过这个程序,我们需要了解Shell中递归函数的编写手段以及当函数的返回值超过255了之后我们如何处理。

2、二分查找

写一个脚本实现二分查找

#!/bin/bash
#用户输入一个数组,要求数组元素必须全部是数字
j=0
for i in $@; do
  array[j++]=$i
done

read -p "Input a number you want to search: " num

function binarySearch(){
   array=$1
   key=$2
   head=0
   tail=$[${#array[@]}-1]
   while [ ${head} -le ${tail} ]; do
       let mid=(head+tail)/2
       if [ "${array[$mid]}" -eq "$key" ]; then
           echo "index of ${key} is  $mid"
           break
       elif [ "${array[$mid]}" -gt "$key" ]; then
           let tail=mid-1
       else
           let head=mid+1
       fi
   done
}

result=`binarySearch "${array[*]}" $num`
if [ -z "$result" ]; then
  echo "Not find key: $num"
else
  echo $result
fi

执行结果:

留言区

还能输入500个字符