c函数引用全局变量出错undefined reference_Shell 脚本中的函数

通过之前发表的文章,相信大家对 Linux Shell 脚本的基本语法有了一定程度的了解,接下来几篇文章我将会介绍一些 Shell 脚本编程的一些高级语法,今天我们就从函数开始。

提到函数,相信有过编程基础的小伙伴都会了解一些,函数其实是我们编码的逻辑单元,无论我们用的面向过程的语言,还是面向对象的语言,函数都是编程中基本的内容。好的函数接口设计,清晰的函数逻辑,巧妙的函数提取,都是对程序员最基本的要求。

创建函数

bash shell中有两种方式创建函数;

1. 通过function 命名函数,格式为

function name {commands}
6df588e86220205f1ece6abfd2eb5163.png

图1

2. 直接通过函数名来创建函数,格式为

name ( ) {commands}
9424b02238290178886c87db02715a2c.png

图2

图1和图2的输出结果相同,为:

./my_scriptthis is functionthis is function

注:在调用函数之前,函数首先要被定义过,也就是说在脚本编写过程中,函数应该在调用之前先被定义,否则会出现函数未定义的错误。其次同名函数如果重复定义,后定义的函数会覆盖之前定义的同名函数。

函数返回值

有时我们在调用函数式,需要通过函数的返回值来判断接下来程序的逻辑,在bash shell中函数通过退出状态码(退出状态码的定义在之前的文章中有介绍)实现函数返回值,并且提供了3种方式来返回函数的退出状态码。

1. 默认退出状态码:

默认状态下,函数通过最后一行命令的返回状态码作为整个函数的状态码返回。这种方式比较危险,可能函数中某些步骤的命令已经出错了,但是最后一行的命令却执行成功,此时作为整个函数的返回码是正确定,那么就掩盖掉错误了。

2. 使用return 语句

可以在函数尾部通过return 语句返回自定义的返回码,例如

function my_func {value=1echo "It is my function"return $[$value+2]}

my_func 函数返回状态码为3. 用return 返回状态码要注意,

  • 函数调用后要立即获取返回状态码
  • 状态码的取值范围为: 0~255。

3. 通过 echo 内容作为函数返回

6686627b06c5680d01f99ca11bfda70e.png

图3

如上图,函数中通过 echo 将其后的内容做为返回值,调用函数后,会将输入的数值翻倍后作为函数输出保存到变量 result 中。

向函数中传递参数

bash shell 函数可以理解为小型脚本,之前的文章中我讲解过如何向脚本中传递参数,所以类似的,向函数中传递参数的方式是一样的。格式为

func1 $param1 $param2...

直接上例子:

4e425153c60a003455eaac8d24620c9a.png

图4

之前向脚本传递参数的讲解中,讲解了如何在脚本中获取参数值,其格式和函数获取参数值得方式一致,通过$0, $1.. 或去对应参数的值,$#获取参数个数。上面的例子中,通过$#判断函数参数个数,如果大于2个或者等于0个,则认为调用失败,返回-1 的状态码。如果参数是1个,则打印这个参数,如果参数刚好2个,则打印两个参数的和。对脚本参数传递有印象的小伙伴可能会有些疑虑,因为函数获取参数值的方式和脚本获取参数值得方式相同,都是通过 $1, $2 ... 来获取第一个,第二个参数的,那么函数的参数会不会覆盖脚本的参数呢?其实这里涉及到作用域的概念,可以裂解为同名但作用域不同。举例:

2d4e916422e49bfa1b80e29be4e84675.png

图5

如上图5, 函数 addem 中通过 $1, $2 来获取传入函数的参数值,函数体外,脚本通过$# 来获取传入脚本的参数个数,然后在then 语句后,通过$1, $2 来获取传递到脚本的参数,然后再将传递进脚本的参数通过调用函数 addem 传递进函数体内。虽然都是通过环境变量 $1, $2 来获取的参数,但是两个变量作用域并不相同,你可以把函数理解为脚本文件中的子脚本。所以没有问题。调用结果如下图6:

2ce03a990c5af78b8c84001ec53b214a.png

图6

变量的作用域

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

  • 全局变量
  • 局部变量

全局变量:顾名思义就是脚本中和函数体内都可以引用的变量。默认情况下,脚本中,函数体外定义的任何变量都是全局变量,函数体内可以直接访问。例如

function my_func {value=$[ $value + 5]}value=2my_funcecho "The new value is: $value"#调用脚本输出结果为:The new value is: 7

上面的例子中,value 在函数体外定义了,是全局变量,所以value值被改变了,在函数体内修改全局变量并不是一个好的主意,所以函数内使用全局变量要特别注意,否则可能会引起错误。

局部变量:函数体内任何变量都可以声明为局部变量,只需要在声明前加上 local 关键字即可。格式为:

local tmpVar

上例子

f2f9894340e8e7a0d074357b18212b3b.png

图7

输出为:

local value is: 20the global value is: 10

从结果可以看出,局部变量 variable 的修改没有影响到全局变量的值。

数组作为函数参数

传递数组给函数,不能讲数组变量作为单独一个变量直接传递给数组,那样只会函数内只能方位到数组的第一个元素,这个原理和C/C++有些相似,C/C++中传递的是数组的指针,所以也只能访问到数组的第一个元素。bash shell 中可以通过将数组分解成单个的值进行传递。直接上例子:

79f372111718a01776a04ef23a514d94.png

图8

输出结果为:

the original array is 1 2 3 4 5the sum result is: 15

数组作为函数返回

e26ef4448059c81de3987382937f3087.png

图9

输出为:

the original array is: 1 2 3 4 5the new array is: 2 4 6 8 10

从图9看出,函数接受数组,并将数组中所有元素翻倍后返回。

创建库

在C/C++工程中,我们经常会将一些通用的函数放到独立的工程中,并将其生成库文件,也就是 lib 文件或者 dll 文件,这样一段函数就可以被不同工程调用,从而减少代码重复。bash shell 中也有类似的库应用,可以将函数创建成库文件,然后被不同的脚本调用。bash shell 中创建库文件的步骤如下:

1. 创建包含所需函数的脚本文件,如下图,创建一个名为 mylib 的库文件

c85e8431332cbbfbe451411216569c5b.png

名字为 mylib 的库文件

2. 在脚本中引用库文件,可以通过source 命令引入库文件到脚本中,source 有一个快捷别名,称为点操作符(dot operator),下图举例脚本中如何引用库文件。

497e65885d2278cc7880df00e44c8a0d.png

图10

图10 为脚本文件,通过点操作符引入库文件,调用mylib中的addem 函数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值