Answers:
保证:
2.9.5功能定义命令
函数是用户定义的名称,用作简单命令以使用新的位置参数调用复合命令。通过“功能定义命令”定义功能。[...]
该函数名为fname; 应用程序应确保它是一个名称(请参阅XBD名称),并且不是特殊内置实用程序的名称。一个实现可以允许函数名称中的其他字符作为扩展名。实现应为函数和变量维护单独的名称空间。
unset
必须使用-v
和-f
在通过给定名称取消设置变量或函数之间进行选择。bash
(与大多数其他shell相对)将在没有变量(!)的情况下取消设置foo
功能,unset foo
这是foo
POSIX允许的行为。这就是为什么在POSIX脚本中始终使用-v
或的好习惯-f
(当然,在bash
脚本中也是如此,但是请注意,unset
可能不会总是在中取消设置变量bash
,bash
变量作用域存在很多问题)。
变量和函数位于破折号中的不同名称空间中,这也由POSIX指定:
实现应为函数和变量维护单独的名称空间。
除此之外,默认情况下,变量具有全局作用域。一些外壳程序(例如bash,ksh和zsh)提供local
关键字以仅在具有局部范围的函数中声明变量。
因此,是的,POSIX保证了您看到的行为。
早期建议中对功能的描述是基于这样的观念,即功能应像微型shell脚本一样运行。也就是说,除了共享变量外,执行环境中的大多数元素都应表现为好像是新的执行环境,[..]
[..]考虑了函数内的局部变量,并将其包含在另一个早期建议中(由特殊内置控件控制
local
),但由于它们不适合为函数开发的简单模型,并且由于添加了一些反对意见而被删除另一个新的特殊内置功能,它不是历史惯例的一部分。如果此局部变量机制在本标准的未来版本中采用,则实现应保留标识符local
(以及typeset
KornShell中使用的标识符)。
(强调我的)
local
那里最一致的接口之一(例如,与bash中严重损坏的接口相比),bash只是最近(4.4)借用了local -
(用于本地范围选项)($-
仅针对该变量实施ash样式作用域)。ksh和yash没有local
(只有pdksh变体有local
),而是有typeset
(在ksh93中,typeset
仅在使用ksh语法声明的函数中提供了本地(静态)范围)。
fn
函数位于单独的命名空间中。如果执行一次删除了其定义,我们将看到完全相同的行为。您应该显示该函数仍处于定义状态,例如type fn
之后。