sh中局部变量的作用域

The scope of local variables in sh

我在调试递归函数时遇到了很多麻烦。事实证明,Dash 对局部变量的解释很奇怪。考虑以下片段:

iteration=0;

MyFunction()
{
    local my_variable;

    iteration=$(($iteration + 1));

    if [ $iteration -lt 2 ]; then
        my_variable="before recursion";
        MyFunction
    else
        echo "The value of my_variable during recursion: '$my_variable'";
    fi
}

MyFunction

在Bash中,结果是:

The value of my_variable during recursion: ''

但在 Dash 中,它是:

The value of my_variable during recursion: 'before recursion'

看起来 Dash 使局部变量在同一函数名称中可用。当我不知道何时以及哪个递归迭代更改了变量的值时,这有什么意义?如何避免问题?

这是由于您试图在最内层的调用中读取变量而未在其中显式设置它的结果。在那种情况下,该变量确实是函数的局部变量,但它从外部上下文(您将其设置为 "before recursion")继承了它的初始值。

因此,变量上的 local 标记仅影响函数调用返回后调用方中变量的值。如果在被调用函数中设置局部变量,它的值不会影响调用者中相同变量的值。

引用 dash 手册页:

Variables may be declared to be local to a function by using a local command. This should appear as the first statement of a function, and the syntax is

 local [variable | -] ...

Local is implemented as a builtin command.

When a variable is made local, it inherits the initial value and exported and readonly flags from the variable with the same name in the surrounding scope, if there is one. Otherwise, the variable is initially unset. The shell uses dynamic scoping, so that if you make the variable x local to function f, which then calls function g, references to the variable x made inside g will refer to the variable x declared inside f, not to the global variable named x.

The only special parameter that can be made local is “-”. Making “-” local any shell options that are changed via the set command inside the function to be restored to their original values when the function returns.

要确定特定上下文中变量的值,请确保始终在该上下文中明确设置它。否则,您依赖于各种 shell 的“后备”行为,这些行为可能因 shell 而异。

local 不是 POSIX 规范的一部分,因此 bashdash 可以按照自己喜欢的方式自由实施。

dash 不允许使用 local 赋值,因此该变量是 unset 除非它从周围范围继承值。 (本例中,第二次迭代的周边范围为第一次迭代。)

bash 确实允许赋值(例如,local x=3),并且总是创建一个变量默认空值,除非进行赋值。