2021-06-11
关键字:
函数就是将一组功能相对独立的代码集中起来,形成一个可供任意调用的代码块的编程形式。
shell中的函数的语法相较于其它编程语言来说要简单很多,具体如下:
函数名 ()
{
语句1
语句2
语句n
}
或者
function 函数名 () { 语句1 语句2 语句n }
建议不要省略 function 关键字。
与传统编程语言不同,shell中的函数对参数的声明是隐式的。它无须像其它编程语言那样指明每个函数需要接受哪些参数以及各个参数的类型。shell函数接受参数的方式是与启动脚本文件一样,通过 $1 , $2, ... , $n 来接收的。如此一来,每个shell函数都可以拥有不定数量个任意类型的参数。
因为shell是从头到尾逐行执行的,因此函数必须在调用之前定义。
函数调用的方式如下所示:
#形式一
function_name
#形式二
function_name param1 param2 param3
可以任意选择带不带参数。
与传统编程语言一样,函数可以嵌套调用,但一个大前提不能少:先定义后调用。
shell函数同样可以拥有返回值。函数执行完毕后返回数据的方式有两种:
1、使用return语句;
2、通过echo语句;
使用return语句返回数据有个限制:只能返回范围为 0 ~ 255 的整数值。直接理解成承载return返回数据的变量为一个字节长度的,超出范围的数值将溢出但不会报错。
使用echo语句倒是可以返回任意类型的数据,但echo语句返回数据属于间接返回的形式。以下直接以一个示例来演示echo在函数中返回数据的方式:
#!/bin/bash function concat_str () { local catted if test $# -eq 2 then catted=$1$2 else echo "You must offer 2 parameters" catted="(null)" fi echo "$catted" } ret=$(concat_str hello world) echo "ret:$ret"
使用”命令替换“的方式来调用函数,将函数内部echo出来的结果封装成外部ret变量的值,从而达到间接返回数据的目的。不过这种使用echo来返回数据的方式要求调用的时候只能使用命令替换的形式。
以上代码将输出如下结果:
ret:helloworld
其实呢,最方便可靠的在函数中返回数据的方式是使用全局变量来承载结果。
shell函数中的参数可以使用 shift 命令来”移位“。
所谓移位就是将原本排在后面的参数往前挪一位,调用一次 shift 命令,将原本第1位的参数剔除掉,将原本第2位的参数挪到第1位来,将原本第3位的参数挪到第2位来,以此类推。
getopts 是一个特殊的命令,用于解析传递给函数的特殊参数。例如我们键入如下命令:
ls -l /etc
这种带-字符的参数用 getopts 来解析就非常方便。
getopts的命令语法如下:
getopts optstring [args]
optstring 用于标注需要被识别的带-的参数,多个参数之间以冒号连接分隔。对应带-的参数后面的值则会被存储在系统变量 $OPTARG 中。下面直接看一个示例来理解:
#!/bin/bash function haha() { while getopts "a:b:c" arg do case "$arg" in a) echo "-param is a" ;; b) echo "-param is b, value:$OPTARG" ;; ?) echo "unknown param" ;; esac done } haha -a i_am_param_a -b param_b -c pc -d pd
上示代码中getopts指定了需要解析的带-参数有a , b , c 三种。其执行结果如下所示:
-param is a -param is b, value:param_b unknown param
因为只解析了a , b , c三种参数,因此最后一个 -d 参数将被忽略。且通过对 -b 的解析也可以确定对应参数的值就是存在系统变量 $OPTARG 变量中的。
另外,其实带-的参数与值之间也不是非得通过空格隔开,直接粘在一起也是可以解析的,如下:
ls -al
此命令将被解析成只带一个 -a 参数的形式,l 是参数 -a 的内容。并非我们想象中的会被解析成两个带-参数,一个 -a 一个 -l,不是这样的,不要太想当然了。
shell中的参数允许”间接传递“。参数间接传递是指某个变量的值又是另外一个变量的名称的情况。如:
var=name
name=chorm
参数间接传递允许直接通过var变量拿到chorm值,其写法如下:
${!var}
与传统编程语言中的头文件类型,shell也允许将某些公共的、常用的功能封装成“库文件”,并允许其它shell脚本文件通过引用库的方式来使用“库文件”中的功能。
具体的做法就是:
1、将要封装的功能在某个单独脚本文件中准备好;
2、在要引用库脚本的地方使用 . 命令 + 库脚本名的方式引入库文件: . lib_file.sh;
其实,可以将引用库文件的小圆点 . 与加载脚本代码的 souce 命令视为是等价的。