mad*_*uri 47 shell bash shell-script function variable
阅读24.2 后。局部变量,我认为var用关键字声明一个变量local意味着它var的值只能在由函数大括号分隔的代码块内访问。
但是,在运行以下示例后,我发现var也可以从该代码块调用的函数中访问、读取和写入 - 即即使var声明local为outerFunc,innerFunc仍然能够读取它并更改其值。
#!/usr/bin/env bash
function innerFunc() {
var='new value'
echo "innerFunc: [var:${var}]"
}
function outerFunc() {
local var='initial value'
echo "outerFunc: before innerFunc: [var:${var}]"
innerFunc
echo "outerFunc: after innerFunc: [var:${var}]"
}
echo "global: before outerFunc: [var:${var}]"
outerFunc
echo "global: after outerFunc: [var:${var}]"
Run Code Online (Sandbox Code Playgroud)
输出:
global: before outerFunc: [var:] # as expected, `var` is not accessible outside of `outerFunc`
outerFunc: before innerFunc: [var:initial value]
innerFunc: [var:new value] # `innerFunc` has access to `var` ??
outerFunc: after innerFunc: [var:new value] # the modification of `var` by `innerFunc` is visible to `outerFunc` ??
global: after outerFunc: [var:]
Run Code Online (Sandbox Code Playgroud)
问:这是我的 shell(bash 4.3.42、Ubuntu 16.04、64 位)中的错误还是预期的行为?
编辑:解决了。正如@MarkPlotnick 所指出的,这确实是预期的行为。
Gil*_*il' 39
Shell 变量具有动态范围。如果将变量声明为函数的局部变量,则该作用域将一直保留到函数返回,包括在调用其他函数期间。
有两个例外:
在 ksh93 中,如果一个函数是用标准function_name () { … }语法定义的,那么它的局部变量服从动态范围。但是如果一个函数是用 ksh 语法定义的,function function_name { … }那么它的局部变量服从词法/静态范围,所以它们在被 this 调用的其他函数中是不可见的。
的zsh/private在autoloadable插件zsh与提供了private关键字/内建可用于声明与静态范围的变量。
ash、bash、pdksh 和衍生物,bosh 只有动态范围。
小智 8
这不是错误,outerFunc 上下文中的调用使用了 $var 的本地副本。externalFunc 中的“本地”意味着全局没有改变。如果在outerFunc 之外调用innerFunc,那么全局$var 会发生变化,但outerFunc 的本地$var 不会发生变化。如果你给innerFunc 添加了“local”,那么outerFunc 的$var 就不会改变——本质上,会有3 个:
使用 Perl 的命名空间格式,有点。
在function innerFunc()该var='new value'虽不及申报地方,因此它可以在可见光范围内(一旦函数被调用)。
相反,function outerFunc()在local var='initial value'被宣布为本地,因此它不是在全球范围内(即使函数被调用)提供。
因为innerFunc()作为 的孩子被调用outerFunc(),所以 var 在 的本地范围内outerFunc()。
man 1 bash 可能有助于澄清
本地 [选项] [名称[=值] ...]
对于每个参数,都会创建一个名为 name 的局部变量,并为其赋值。该选项可以是declare 接受的任何选项。在函数中使用 local 时,它会导致变量名称的可见范围仅限于该函数及其子函数。...
这是一个在描述预期隐含的行为可以通过声明来实现local var='new value的function innerFunc()。
正如其他人所说,这不是 bash shell 中的错误。一切都在正常运作。