shell脚本系列:4、shell函数

shell脚本系列:4、shell函数



Shell函数是一种将命令分组的方法,以便稍后使用组的单个名称执行。它们就像“常规”命令一样被执行。当使用shell函数名作为简单的命令名时,将执行与该函数名相关的命令列表。Shell函数在当前Shell上下文中执行;没有创建新的进程来解释它们。

1. 函数语法

函数的声明语法如下:

fname () compound-command [ redirections ]

或者(在有的时候不带function解释器识别不了,所以一般还是加上好一些):

function fname [()] compound-command [ redirections ]

这定义了一个名为fname的shell函数。保留字功能是可选的。如果提供了函数保留字,括号是可选的。函数的主体是复合命令compound-command(参见复合命令)。该命令通常是一个包含在{和}之间的列表,但也可以是上面列出的任何复合命令,但有一个例外:如果使用了函数保留字,但没有提供括号,则需要使用大括号。只要指定fname为命令名,就执行复合命令。当shell处于POSIX模式时(请参阅Bash POSIX模式),fname必须是一个有效的shell名称,并且可能与特殊内置(请参阅特殊内置)不同。在默认模式下,函数名可以是任何不包含$的不带引号的shell字。与shell函数相关的任何重定向(请参阅重定向)都将在执行该函数时执行。可以使用-f选项删除未设置的内置函数(参见Bourne Shell内置函数)。

函数定义的退出状态为零,除非出现语法错误或已存在同名的只读函数。当执行时,函数的退出状态是函数体中最后执行的命令的退出状态。

2. 注意事项

注意,由于历史原因,在最常见的用法中,包围函数体的花括号必须用空格或换行符与函数体分隔。这是因为大括号是保留字,只有当它们以空格或另一个shell元字符与命令列表分隔时才被识别为保留字。此外,当使用大括号时,列表必须以分号、’ & '或换行符结束。

当一个函数被执行时,函数的参数在其执行期间成为位置参数(参见位置参数)。扩展到位置参数数量的特殊参数’ # '将被更新以反映更改。特殊参数0不变。在执行函数时,FUNCNAME变量的第一个元素被设置为函数的名称。

shell执行环境的所有其他方面在函数和它的调用者之间是相同的,除了这些例外:DEBUGRETURN陷阱并非继承,除非函数提供trace属性、使用declare内置 或- o functrace选项被启用set内置(在这种情况下,继承了所有功能DEBUGRETURN陷阱),ERR陷阱并不继承,除非- o errtrace shell选项已启用。请参阅Bourne Shell Builtins,以获得对内置陷阱的描述。

如果FUNCNEST变量被设置为一个大于0的数值,那么它将定义一个最大的函数嵌套级别。超过限制的函数调用将导致整个命令中止。

如果在函数中执行内置命令return,则函数完成并在调用函数后继续执行下一个命令。在恢复执行之前,与RETURN 缺陷相关的任何命令都会被执行。当函数完成时,位置形参和特殊形参’ # '的值将恢复为函数执行前的值。如果返回一个数值参数,那就是函数的返回状态;否则函数的返回状态是返回之前执行的最后一个命令的退出状态。

3. 函数变量作用域

函数的局部变量可以用local内置函数声明。这些变量只对函数及其调用的命令可见。当一个shell函数调用其他函数时,这一点尤其重要。

局部变量会“遮蔽”在前面作用域中声明的同名变量。例如,函数中声明的局部变量隐藏同名的全局变量:引用和赋值引用局部变量,而不修改全局变量。当函数返回时,全局变量再次可见。

shell使用动态范围来控制变量在函数中的可见性。使用动态作用域,可见变量及其值是导致执行到达当前函数的函数调用序列的结果。函数看到的变量的值取决于它在调用者中的值(如果有的话),该调用者是“全局”作用域还是另一个shell函数。这也是局部变量声明“阴影”的值,也是函数返回时恢复的值。

例如,如果一个变量var在函数func1中声明为局部变量,而func1调用另一个函数func2,在func2中对var的引用将解析为func1中的局部变量var,从而遮蔽任何名为var的全局变量。

下面的脚本演示了这种行为。执行时,将显示:

In func2, var = func1 local
func1()
{
    local var='func1 local'
    func2
}

func2()
{
    echo "In func2, var = $var"
}

var=global
func1

unset内置变量也使用相同的动态作用域:如果一个变量是当前作用域的局部变量,unset将取消它的设置;否则unset将引用上述任何调用范围内的变量。如果当前局部作用域的变量未被设置,它将一直保持此状态,直到在该作用域中被重置或函数返回为止。一旦函数返回,该变量在前一个作用域的任何实例都将可见。如果unset作用于前一个作用域的变量,则带有该名称的变量的任何实例将变为可见。

4. 其它

函数名和定义可以在declare(typeset)内置命令(参见Bash Builtins)中用-f选项列出。用于declaretypeset-F选项将只列出函数名(如果启用了extdebug shell选项,还可以选择列出源文件和行号)。函数可以被导出,以便子Shell自动将它们用-f选项定义到导出内置(参见Bourne Shell内置)。

函数可以是递归的。FUNCNEST变量可以用来限制函数调用堆栈的深度和函数调用的数量。默认情况下,没有对递归调用的数量进行限制。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昵称系统有问题

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值