什么是函数?对程序逻辑的封装、可以实现代码的复用、并且在一个位置修改,可以实现多个位置使用(还是复用)。
shell是面向过程的语言,所以shell封装一般都是函数或者库。
基本的脚本函数
shell中所指的函数是可以命名的,并在代码中任何位置重复使用的代码块。
函数的定义
两种函数定义的方式:
function name {
commands
}
name() {
command
}
两种方法完全等价
Linux中,文件的后缀名对于计算机没有什么意义(不同于Windows),只是为了操作人员方便管理文件和查找文件
Windows根据文件后缀名判定文件的种类,从而知道其格式和用途,进而选择打开方式和软件
写一个简单实例:
[root@shell shell]# vim func.sh //编辑脚本文件func.sh [root@shell shell]# bash func.sh //执行脚本 hello func1 hello func2 [root@shell shell]# cat func.sh //脚本中的具体内容 #!/bin/bash function func1 { echo "hello func1" } func1 func2() { echo "hello func2" } func2
如果在函数定义前,就调用函数,系统会抛出错误
[root@shell shell]# vim func_error.sh [root@shell shell]# bash func_error.sh //执行后,抛出错误 func_error.sh: line 3: func: command not found [root@shell shell]# cat func_error.sh //具体脚本内容 #!/bin/bash func //先调用了函数,在函数func定义之前 func () { echo "hello func" }
函数的返回值
退出码
一个shell脚本运行结束后,会有一个退出码,可以使用echo $?
来对状态码进行访问。
[root@shell shell]# ls add.sh bc.sh envpath func_error.sh func.sh helloworld [root@shell shell]# bash func.sh hello func1 hello func2 [root@shell shell]# echo $? 0 //正常结束后,返回值为0
如果函数非正常退出,则返回其他值(127代表-1?)
[root@shell shell]# bash func.sh //此处将上面的func.sh代码中func2改成了func3(不存在func3函数) hello func1 func.sh: line 11: func3: command not found [root@shell shell]# echo $? 127
$?是指返回上一次执行结果的返回值,所以执行完代码后,应该立即执行echo $?
return命令
如果要让返回值变的有意义,就要使用return
命令,可以在函数中定义。
如:
[root@shell shell]# vim func.sh [root@shell shell]# bash func.sh hello func1 hello func2 [root@shell shell]# echo $? 24 [root@shell shell]# cat func.sh #!/bin/bash function func1 { echo "hello func1" return 23; } func1 func2() { echo "hello func2" return 24 } func2
退出的状态码,必须在0-255之间
函数输出
在实际使用时,我们希望函数通过自定义的形式处理输出。如:使用变量保存输出
[root@shell shell]# vim func.sh [root@shell shell]# bash func.sh hello func1 hello func2 hello func2 [root@shell shell]# cat func.sh #!/bin/bash function func1 { echo "hello func1" return 23; } func1 func2() { echo "hello func2" return 24 } func2 var= func2 //用变量保存函数执行后的值 echo $var
函数中的变量使用
函数参数变量
[root@shell shell]# cat add #!/bin/bash add() { //定义一个函数,名为add if [ $# -eq 2 ];then //判断,参数个数是否为 2 ,$#意思时参数个数 result=$[ $1+$2 ] //如果为 2 ,则执行假法操作,并用result保存 echo $result //输出reslut值 else //否则 echo "input error" //输出“输入有误” return 1 //return返回码为1 fi } value=`add $1 $2` //定义变量保存函数执行结果,注意:此处" = "左右不能有空格 if [ $? -eq 0 ];then //判断是否函数结束返回码为0,如果为0,则表示执行加法操作成功 echo $value //返回value结果 else //否则 echo "err:$value" //输出失败,和value值 fi [root@shell shell]# ./add 2 3 //成功示例 5 [root@shell shell]# ./add 2 //失败示例 err:input error
如何在函数中处理数组参数
第一个脚本示例(如何定义和引用数粗):
错误示例:
[root@shell shell]# cat test_array.sh #!/bin/bash testarray() { echo "$@" //输出所有参数值 echo "$1" //输出第一个参数值 echo "$2" //输出第二个参数值 echo "$#" //输出参数个数 } array=(1 2 3 4 5 6 7) //定义一个数组,和C语言不同,数组元素空格隔开,且是小括号括起来 testarray $array //这种调用数组的方式是错误的 [root@shell shell]# bash test_array.sh 1 1 1
正确的方式:
[root@shell shell]# cat test_array.sh #!/bin/bash testarray() { echo "$@" echo "$1" echo "$2" echo "$#" } array=(1 2 3 4 5 6 7) testarray ${array[*]} //正确形式,表明传入的参数是一个数组 echo ${array[4]} //进一步理解,[数字]类似下标,表示第几个元素,下标从0开始计数 [root@shell shell]# bash test_array.sh 1 2 3 4 5 6 7 1 2 7 5
第二个脚本示例(数组所有元素求和)
[root@shell shell]# cat test_array.sh #!/bin/bash sum() { result=0 for var in $@ do result=$[ $result+$var ] done echo $result newarray=(`echo $@`) //将数组array的元素写入到一个新的数组newarray里 echo ${newarray[*]} //输出新数粗里面的所有元素 } array=(1 2 3 4 5 6 7) sum ${array[*]} [root@shell shell]# bash test_array.sh 28 1 2 3 4 5 6 7
$@显示的是所有的参数
函数中参数的作用域
函数可以使用两种类型的变量,全局变量和局部变量,shell中定义变量默认都是全局变量。
local
关键字,将全局变量改变为局部变量。
如果不使用local关键字:
[root@shell shell]# cat local.sh #!/bin/bash sum() { result=0 for var in $@ do result=$[ $result+$var ] done echo "inside $result" } array=(1 2 3 4) sum ${array[*]} echo "outside $result" [root@shell shell]# bash local.sh inside 10 outside 10
很显然,我们不希望出现在函数体内定义的变量,被外部访问到。所以需要local
关键字
[root@shell shell]# vim local.sh [root@shell shell]# cat local.sh #!/bin/bash sum() { local result=0 for var in $@ do result=$[ $result+$var ] done echo "inside $result" } array=(1 2 3 4) sum ${array[*]} echo "outside $result" [root@shell shell]# bash local.sh inside 10 outside //这样就无法房屋函数体内的变量
使用函数库
什么是函数库?对一系列函数的封装。是函数更上一层封装。
在shell中,函数库就是包含可重用函数的脚本文件
创建一个包含函数的脚本文件
如何创建包含一系列函数的脚本文件:
[root@shell shell]# vim func_2.sh //编辑一个函数脚本文件 [root@shell shell]# cat func_2.sh //该脚本文件里面只有函数的定义 #!/bin/bash add() { //定义第一个函数add,实现两个数加法运算 if [ $# -eq 2 ];then result=$[ $1+$2 ] echo $result else echo "input error" return 1 fi } sum() { //定义第二个函数sum,实现一个数组元素求和 result=0 for var in $@ do result=$[ $result+$var ] done echo $result }
脚本文件编辑完成,如何使shell进程读取9即,如何引用函数库文件)?
在其他脚本中引用函数库文件
命令行引用方法
source filepath
== . filepath
[root@shell shell]# source func_2.sh //让shell进程识别并加载func_2.sh脚本文件 [root@shell shell]# add //source结束就可以使用里面定义的函数 input error [root@shell shell]# add 2 3 5 [root@shell shell]# arr=(1 2 3) [root@shell shell]# sum ${arr[*]} 6
脚本中引用方法
用一个脚本调用函数库文件方法:
[root@shell shell]# cat use_func_2.sh #!/bin/bash source ./func_2.sh //类似命令行,刷新当前目录中的函数库文件,调用加载函数库文件 echo `add 12 34` //调用函数库文件中的add函数,并输出结果 array=(1 2 3 4 5) echo `sum ${array[*]}` //调用函数库文件中的sum函数,并输出结果 [root@shell shell]# bash use_func_2.sh 46 15
在bash启动时,自动加载函数库
在~/.bashrc
文件下添加,在该文件最后添加:
source /mnt/shell/func_2.sh
在重新打开一个shell后,可以直接使用该函数库。这也时定义一个全局函数库的方法。