十七 函数
函数是一个脚本代码块,在代码任何位置中重用;使用时通过函数名调用既可;
1.1 创建函数
bash shell有两种常见函数的方式:
- 采用关键字function
- 如常见编程语言的函数定义方式
1.1.1 function关键字方式创建函数
格式:
function 函数名{
命令
}
在同一脚本中定义的函数名必须是唯一的;
1.1.2 常见编程语言的函数定义方式
格式:
函数名(){
}
注意:
- 在脚本中如果函数定义前调用函数就会报错;即调用必须在定义之后;
- 如果在脚本中定义连个同名函数,在后一个函数定义后调用的就是就是后一个函数,而不是第一个函数;
1.2 函数返回值
bash shell把函数当成一个小型的脚本,函数执行完成后,会返回一个命令退出状态码;
有三种方式来生成函数退出状态:
1.2.1 默认退出状态码:
默认情况,函数退出状态码是函数最后一条命令返回 的退出状态码;在函数执行结束后,用标准变量“&?”来接受函数退出码;
缺陷:这种方式不知道函数中前面的命令是否执行成功
1.2.2 return命令
允许指定一个整数来指定函数的退出码;
使用这种显示方式来指定函数返回值,必须记住两条:
- 函数一结束就返回值
- 退出状态码必须是0-255,如果大于该值,就返回一个错误值;
注意:在调用函数后,必须立即“ ? ” 来 接 受 函 数 返 回 值 , 中 间 不 能 调 用 其 他 命 令 , 否 则 函 数 返 回 值 会 丢 失 , “ ?”来接受函数返回值,中间不能调用其他命令,否则函数返回值会丢失,“ ?”来接受函数返回值,中间不能调用其他命令,否则函数返回值会丢失,“?”变量会返回执行的最后一条命令的退出状态码;
#!/bin/bash
say(){
read -p "please input the value:" value
return "$[ $value * 2 ]"
}
say
echo "hello world"
echo "the result is :$?"
将丢失函数返回值,返回echo “hello world”命令的退出状态码,将输出:
[root@Linleslie codetest]# ./test36
please input the value:10
hello world
the result is :0
[root@Linleslie codetest]#
1.2.3 函数输出
和前面说的将命令输出保存到shell变量中一样,也可以将函数输出保存到变量中;函数的返回值为最后一条命令的输出,而不是返回最后一条命令的退出状态码;
优点:很好的避免第二种方式只能返回0-255这整数范围内的缺陷;
如:
#!/bin/bash
say(){
read -p "please input the value:" value
echo "$[ $value * 2 ] "
}
result=$(say)
echo "the function return value is :$result"
这儿函数的返回值就是
1.3 向函数传递参数
我们说过bash shell把函数当做小型脚本对待,意味着你可以像普通脚本那样向函数传递参数;
函数中用标准的环境变量(相当于函数形参)来表示命令行上传递给函数的参数(相当于实参),函数名在$0中定义,命令行上的任何参数都会通过$1、$2等定义;也可以用特殊变量"$#"来表示传递给函数的参数个数;
注意:
- 函数中使用的特殊参数环境变量,其值必须是我们调用函数时传入的,无法获取运行脚本在命令行中传入的值;
- 前面我们说了可以脚本向脚本中传递值,然后在脚本中用特殊变量接收($1、$2…),而函数可以看作一个小型脚本,在调用函数时也可以传入值,在函数中用$1、$2…接收;函数中使用的$1和脚本中使用的$1变量并不同,前者必须是调用函数时传入,后者必须是脚本命令行中传入;
1.4 变量作用域
局部变量:只在函数中使用的变量,只在函数内部有效
在函数中用local关键字定义局部:
local 变量名
全局变量:在脚本中定义的变量,脚本中、函数中都可以使用该变量 ,即使该变量定义在函数定义后也没问题;
由于局部变量只在函数总有效,如果存在同名局部变量和全局变量,就可以正常区分了,在函数外访问的全局变量,在函数内局部变量会覆盖全局变量,所以访问的是局部变量;
#!/bin/bash
temp=4
say(){
local temp=10
echo "$temp"
}
say
echo "$temp"
输出的是:10 4
1.5 数组变量
1.5.1 向数组传递数组参数
1.6 创建函数库文件
如果在多个脚本都需要调用同一函数,通过定义库文件,然后在多个脚本中引用,就可以避免在每个脚本中定义同样的函数的麻烦;
使用库文件命令:
source
source命令:在当前shell上下文中执行命令,而不是创建一个新的shell,用来在shell脚本中运行库文件脚本;
source命令有个快捷的别名,叫做点操作符,要在shell脚本中运行库文件,只需添加下面这行:
. ./库文件名
// ./文件名:表示库文件在当前目录,如果不是需要指定其全路径
这个例子是假定脚本和库文件在同一目录,如果不在同一目录,需要指定库文件路径
1.7 命令行上使用函数
1.7.1 在命令行上创建函数
方式一:单行方式定义函数
function say{echo “hello”;
echo “world”;}
必须在每个命令末尾添加分号,用于辨别命令起始
方式二:采用多行定义
function say{
> echo "hello"
> echo "world"
> }
采用次提示符">"来输出更多命令,每条命令末尾无需添加分号;
***注意:***如果你创建的函数名和内建命令名相同,将会发生函数覆盖命令的情况,以避免这种情况发生;
该种方式缺点:一旦shell退出,函数消失;
1.7.2 在.bashrc文件中定义函数
将函数定义在一个特定的位置,每次启动新shell时,都会由shell重新载入;而这个位置就是.bashrc文件,bash shell在每次启动时都会在主目录中查找这个文件,不管是交互式shell还是现有shell中启动新的shell;
-
直接打开.bashrc文件,将函数追加多.bashrc文件
# .bashrc ......... //-------------- say(){ echo "hello world" }
-
直接在.bashrc使用source命令将库文件函数添加到.bashrc文件
# .bashrc ......... //-------------- if [ -r /etc/bashrc ] then . /etc/bashrc fi . /tmp/codetest/lib
shell会将定义好的函数传递给子进程,这些函数就自动能够用于该shell会话中的任何shell脚本了;(但是实测不行,不知道原因)
# .bashrc
.........
//--------------
if [ -r /etc/bashrc ]
then
. /etc/bashrc
fi
. /tmp/codetest/lib
shell会将定义好的函数传递给子进程,这些函数就自动能够用于该shell会话中的任何shell脚本了;(但是实测不行,不知道原因)
[外链图片转存中…(img-4ME5KU5r-1592469654329)]