函数

bash中的函数类似于C/C++中的函数,但return的返回值与C/C++不同,返回的是exit code,取值为0-255,0表示正常结束。

如果想获取函数的输出结果,可以通过echo输出到stdout中,然后通过$(function_name)来获取stdout中的结果。

函数的return值可以通过$?来获取。

命令格式:

[function] func_name() {  # function关键字可以省略
   语句1
   语句2
   ...
}

不获取 return值和stdout值

示例

func() {
   name=yxc
   echo "Hello $name"
}

func

输出结果:

Hello yxc

获取 return值和stdout值

不写return时,默认return 0。

示例

func() {
   name=yxc
   echo "Hello $name"

   return 123
}

output=$(func)
ret=$?

echo "output = $output"
echo "return = $ret"

输出结果:

output = Hello yxc
return = 123

函数的输入参数

在函数内,$1表示第一个输入参数,$2表示第二个输入参数,依此类推。

注意:函数内的$0仍然是文件名,而不是函数名。

示例:

func() {  # 递归计算 $1 + ($1 - 1) + ($1 - 2) + ... + 0
   word=""
   while [ "${word}" != 'y' ] && [ "${word}" != 'n' ]
   do
       read -p "要进入func($1)函数吗?请输入y/n:" word
   done

   if [ "$word" == 'n' ]
   then
       echo 0
       return 0
   fi

   if [ $1 -le 0 ]
   then
       echo 0
       return 0
   fi

   sum=$(func $(expr $1 - 1))
   echo $(expr $sum + $1)
}

echo $(func 10)

输出结果:

55

为什么只输出55不输出其他的值:只要在 $(func) 这样的命令替换里,这个 $() 就会截获掉函数内所有 echo 写进 stdout 的值,使得这些 echo 的内容不再显示到屏幕上。在递归往回调用的过程中,上一层的 echo 会被这一层的 sum=$(func $(expr $1 - 1)) 中的第一个 $() 捕获从而没有输出,而最后一层的 echo 会被函数外的 echo $(func 10)$() 捕获,因此是函数外的 echo 输出的 55。如果你把函数外的 echo $(func 10) 改成 func 10,输出的 55 就是最后一层递归里 echo $(expr $sum + $1) 输出的。

函数内的局部变量

可以在函数内定义局部变量,作用范围仅在当前函数内。

可以在递归函数中定义局部变量。

命令格式:

local 变量名=变量值

例如:

#! /bin/bash

func() {
   local name=yxc
   echo $name
}
func

echo $name

输出结果:

yxc

第一行为函数内的name变量,第二行为函数外调用name变量,会发现此时该变量不存在。

⚠️函数使用注意事项
  • 先定义后调用:bash 按行解释执行脚本,调用发生在定义之前会报 command not found(这与 C/C++ 需要前置声明的道理类似)。
  • 函数名与 C/C++ 标识符规则相同:字母、数字、下划线,不能以数字开头,且不能与内置命令同名(如 cdexit),否则会覆盖内置行为。
  • 函数内同样可以使用默认变量一节的所有符号:$# 表示传入函数的参数个数,$@ 表示所有参数,只有 $0 例外——它仍然是脚本文件名而不是函数名。
  • local 只能在函数内使用;在函数外写 local 会报错。递归函数中务必对会变的变量用 local,否则递归各层共享同名全局变量,结果会错乱。

项目分区导航循环语句 ⬅️ | 18-函数 | ➡️ exit命令