Skip to content

创建函数

基本的脚本函数

创建函数

有两种格式

bash
function name {
	commands
}

注意空格

bash
name() { 
	commands
}

使用函数

要使用函数直接指定函数名就可以了

bash
  1 #!/bin/bash                                                                           
  2 
  3 function func1 {
  4     echo "This is an example of an function"
  5 }
  6 count=1
  7 while [ $count -le 5 ]
  8 do
  9     func1
 10     count=$[ $count+1 ]
 11 done
 12 
 13 echo "This is the end of the loop"
 14 func1
 15 echo "This is the end of the scrip"
 
 
jiao@jiao-virtual-machine:~/桌面/linux-shell/17$ test1.sh 
This is an example of an function
This is an example of an function
This is an example of an function
This is an example of an function
This is an example of an function
This is the end of the loop
This is an example of an function
This is the end of the scrip

函数名必须是唯一的,否则也会有问题。如果你重定义了函数,新定义会覆盖原来函数的定义,这一切不会产生任何错误消息

返回值

bash shell 会把函数当成一个小的脚本, 运行结束返回退出状态码

默认退出状态码

默认情况下,函数的退出状态码是函数中最后一条命令返回的退出状态码。在函数执行结束后,可以用标准变量$?来确定函数的退出状态码

函数中的其他命令出现错误没有体现

使用return命令

l使用return命令来退出函数并返回特定的退出状态码

  • 函数一结束就取返回值;
  • 退出状态码必须是0~255

使用函数输出

把要输出的值放在变量中

bash
result='dbl'

新函数会用echo语句来显示计算的结果。该脚本会获取dbl函数的输出,而不是查看退出状态码

bash shell脚本非常聪明,并不将其作为STDOUT输出的一部分,并且忽略掉它。如果你用echo语句生成这条消息来向用户查询,那么它会与输出值一起被读进shell变量中

可以通过这种方法返回各种值

bash
  1 #!/bin/bash
  2 
  3 function db1 {
  4     read -p "Enter a value: " value
  5     echo "value is $[ value * 2 ]"
  6 }
  7 result=$(db1)
  8 echo "The new $result"                
  
jiao@jiao-virtual-machine:~/桌面/linux-shell/17$ test4.sh 
Enter a value: 34
The new value is 68

在函数中使用变量

向函数传递参数

可以吧函数当做小型的脚本, 可以直接传递参数

bash
func1 $value1 10
bash
  1 #!/bin/bash                                                                           
  2 
  3 function addem {
  4     if [ $# -eq 0 ] || [ $# -gt 2 ]
  5     then
  6         echo -1
  7     elif [ $# -eq 1 ]
  8     then
  9         echo $[ $1+$1 ]
 10     else
 11         echo $[ $1 + $2 ]
 12     fi
 13 
 14 }
 15 
 16 echo -n "Add 10 and 15: "
 17 value=$(addem 10 15)
 18 echo $value
 19 echo -n "Let's try adding just one number: " 
 20 value=$(addem 10) 
 21 echo $value 
 22 echo -n "Now trying adding no numbers: " 
 23 value=$(addem) 
 24 echo $value 
 25 echo -n "Finally, try adding three numbers: " 
 26 value=$(addem 10 15 20) 
 27 echo $value

jiao@jiao-virtual-machine:~/桌面/linux-shell/17$ test5.sh 
Add 10 and 15: 25
Let's try adding just one number: 20
Now trying adding no numbers: -1
Finally, try adding three numbers: -1

由于函数使用特殊参数环境变量作为自己的参数值,因此它无法直接获取脚本在命令行中的参数值, 它们和脚本主体中的$1和$2变量并不相同。

在函数中处理变量

函数使用两种类型的变量:

  • 全局变量
  • 局部变量

全局变量

默认情况下, 在脚本中定义的变量都是全局变量, 函数外定义的变量都可以在函数中正常访问

bash
  1 #!/bin/bash                                                                           
  2 
  3 function db1 {
  4     value=$[ $value*2 ]
  5 }
  6 read -p "Enter a value: " value
  7 db1
  8 echo "The new value is : $value"

jiao@jiao-virtual-machine:~/桌面/linux-shell/17$ myts.sh test6.sh 
Enter a value: 45
The new value is : 90

局部变量

在变量之前加上local, 一般是在函数内使用

数组变量和函数

向函数传递数组变量

  • 错误示范
bash
  1 #!/bin/bash                                                                           
  2 
  3 function testit {
  4     echo "The parameters are: $@"
  5     thisarray=$1
  6     echo "The receive array is ${thisarray[*]}"
  7 
  8 }
  9 myarray=(1 2 3 4 5)
 10 echo "The original array is: ${myarray[*]}"
 11 testit $myarray
 12 echo $myarray
 
 jiao@jiao-virtual-machine:~/桌面/linux-shell/17$ myts.sh test7.sh 
The original array is: 1 2 3 4 5
The parameters are: 1
The receive array is 1
1

传递的只是第一个参数

bash
  1 #!/bin/bash
  2 
  3 function testit {
  4     local newarray   
  5     newarray=$( echo "$@" )   
  6     echo "The new array value is: ${newarray[*]}"
  7 }
  8 myarray=(1 2 3 4 5)
  9 echo "The original array is: ${myarray[*]}"
 10 testit ${myarray[*]}
 
jiao@jiao-virtual-machine:~/桌面/linux-shell/17$ test7.sh 
The original array is: 1 2 3 4 5
The new array value is: 1 2 3 4 5

从函数返回数组

函数用echo语句来按正确顺序输出单个数组值,然后脚本再将它们重新放进一个新的数组变量中

bash
  1 #!/bin/bash                                                                           
  2 
  3 function arrayblr {
  4     local origarray
  5     local newarray
  6     local elements
  7     local i 
  8     origarray=($(echo "$@"))
  9     newarray=($(echo "$@"))
 10     elements=$[ $# -1 ]
 11     for ((i=0 ; i<=elements; i++))
 12     {
 13         newarray[$i]=$[ ${origarray[$i]} * 2 ]
 14     }
 15     echo ${newarray[*]}
 16 }
 17 myarray=(1 2 3 4 5)
 18 echo "The original array is: ${myarray[*]}"
 19 arg1=$(echo ${myarray[*]})
 20 result=($(arrayblr $arg1))
 21 echo "The new array is: ${result[*]}" 
 
jiao@jiao-virtual-machine:~/桌面/linux-shell/17$ test8.sh 
The original array is: 1 2 3 4 5
The new array is: 2 4 6 8 10

函数递归

bash
  1 #!/bin/bash                                                                           
  2 function factorial {
  3     if [ $1 -eq 1 ]
  4     then
  5         echo 1
  6     else
  7         local temp=$[ $1-1 ]
  8         local result=` factorial $temp `
  9         echo $[ $result * $1 ]
 10     fi
 11 }
 12 
 13 read -p "Enter your value: " value
 14 result=$(factorial $value )
 15 echo $result

创建库

source命令会在当前shell上下文中执行命令,而不是创建一个新shell。可以用source命令来在shell脚本中运行库文件脚本。

source命令有个快捷的别名,称作点操作符(dot operator)。要在shell脚本中运行myfuncs库文件,只需添加下面这行:

bash
. ./myfuncs
bash
  1 #/bin/bash                                                                            
  2 . ./myfunc
  3 value1=10
  4 value2=5
  5 result1=$(addem $value1 $value2)
  6 result2=$(multem $value1 $value2)
  7 result3=$(diven $value1 $value2)
  8 echo $result1
  9 echo $result2
 10 echo $result3

jiao@jiao-virtual-machine:~/桌面/linux-shell/17$ test11.sh 
15
50
2

在命令行上使用函数

因为一旦在shell中定义了函数,你就可以在整个系统中使用它了,无需担心脚本是不是在PATH环境变量里。重点在于让shell能够识别这些函数。有几种方法可以实现

在命令行上创建函数

因为shell会解释用户输入的命令,所以可以在命令行上直接定义一个函数。有两种方法。一种方法是采用单行方式定义函数

bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/17$ function divem { echo $[ $1 / $2 ]; } 
jiao@jiao-virtual-machine:~/桌面/linux-shell/17$ divem 8 4
2

当在命令行上定义函数时,你必须记得在每个命令后面加个分号,这样shell就能知道在哪里是命令的起止了。

另一种方法是采用多行方式来定义函数。在定义时,bash shell会使用次提示符来提示输入更多命令。用这种方法,你不用在每条命令的末尾放一个分号,只要按下回车键就行

bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/17$ function multem {
> echo $[ $1 * $2 ]
> }
jiao@jiao-virtual-machine:~/桌面/linux-shell/17$ multem 5 4
20

在命令行上创建函数时要特别小心。如果你给函数起了个跟内建命令或另一个命令相同的名字,函数将会覆盖原来的命令

在.bashrc文件中定义函数

  • 直接定义函数
  • 读取函数文件

更好的是,shell还会将定义好的函数传给子shell进程,这样一来,这些函数就自动能够用于该shell会话中的任何shell脚本了

实例

你可以下载大量各式各样的函数,并将其用于自己的应用程序中

使用GNU shtool库下载并安装到你的系统中

bash
wget ftp://ftp.gnu.org/gnu/shtool/shtool-2.0.8.tar.gz
tar -zxvf shtool-2.0.8.tar.gz

库函数

函数描述
Arx创建归档文件(包含一些扩展功能)
Echo显示字符串,并提供了一些扩展构件
fixperm改变目录树中的文件权限
install安装脚本或文件
mdate显示文件或目录的修改时间
mkdir创建一个或更多目录
Mkln使用相对路径创建链接
mkshadow创建一棵阴影树
move带有替换功能的文件移动
Path处理程序路径
platform显示平台标识
Prop显示一个带有动画效果的进度条
rotate转置日志文件
Scpp共享的C预处理器
Slo根据库的类别,分离链接器选项
Subst使用sed的替换操作
Table以表格的形式显示由字段分隔(field-separated)的数据
tarball从文件和目录中创建tar文件
version创建版本信息文件
bash
jiao@jiao-virtual-machine:~/shtool-2.0.8$ test12.sh | shtool prop -p "Waiting..."
Waiting...

会显示一个简单的动画, 并且不输出原来的内容, 输出定义的内容

能看到多少进度条取决于CPU能以多快的速度列出/usr/bin中的文件!-p选项允许你定制输出文本,这段文本会出现在进度条字符之前

bash
jiao@jiao-virtual-machine:~/shtool-2.0.8$ shtool platform
Ubuntu 21.10 (AMD64)