我设计了一个简单的测试来查看Bash如何使用递归操作,但我不理解结果。
测试:
Xf(),该函数分配同名的变量local Xlocal X分配全局X的值,即local X=$XX还是使用上一轮函数中的local X我期望两种结果中的一种:
local X的f()将是新的“全局”X,即下一个向上作用域中的X,这将指示每个递归在前一个作用域下创建一个新的范围。local X值,而每个新的local X=$X将简单地重新分配我最初分配的全局X的值。这表明Bash创建了相邻的作用域。我没有收到任何这些。我有奇怪的东西。下面是来自终端的复制粘贴。
我在shell中赋值一个全局变量:
user@ubuntu-zesty:~$ X=1我在shell中创建一个函数f(),该函数创建local X,将全局X的值赋值给它,进入一个while循环,将1添加到local X (假设它是本地的),打印新的local X值,并调用自己。重复5或6次。
user@ubuntu-zesty:~$ f() { local X=$X; while [ $X -lt 6 ]; do X=$(( $X + 1 )); echo $X; sleep 1; f; done; }然后我调用f(),输出就是令人费解的。
user@ubuntu-zesty:~$ f
2
3
4
5
6
6
5
6
6
4
5
6
6
5
6
6
3
4
5
6
6
5
6
6
4
5
6
6
5
6
6在这一点上,它自己退出。正如预期的那样,全球X没有受到影响。
user@ubuntu-zesty:~$ echo $X
1这是怎么回事?它有时使用全局X,有时使用local X?如果你知道这里发生了什么,请不要放过我血淋淋的细节。
最后,为了好玩,输出的图表:
1 ==
2 ===
3 ====
4 =====
5 ======
6 ======
7 =====
8 ======
9 ======
10 ====
11 =====
12 ======
13 ======
14 =====
15 ======
16 ======
17 ===
18 ====
19 =====
20 ======
21 ======
22 =====
23 ======
24 ======
25 ====
26 =====
27 ======
28 ======
29 =====
30 ======
31 ======规格:
发布于 2017-04-05 20:11:14
我认为,如@chepner在其回答中所解释的那样,可视化动态范围的最佳方法是稍微修改您的功能:
function f() {
local X="$X"
while [ "$X" -lt 6 ]; do
X=$((X + 1))
echo "${FUNCNAME[*]}" "$X" # This will print the call stack
sleep 1
f
done
}并查看值是如何增加的:如果遵循输出列,则可以调试每个级别发生的情况。
$ f
f f f f f 2
f f f f f f 3
f f f f f f f 4
f f f f f f f f 5
f f f f f f f f f 6
f f f f f f f f 6
f f f f f f f 5
f f f f f f f f 6
f f f f f f f 6
f f f f f f 4
f f f f f f f 5
f f f f f f f f 6
...发布于 2017-04-05 19:58:02
bash是动态作用域,而不是静态作用域(也称为词汇范围)。这意味着在执行行local X=$X时,并不是根据在全局词法作用域分配的值来获得$X的值,而是基于最近的运行时作用域中存在的值,即调用f的作用域中的值。这意味着一个局部值不仅在函数调用中可见,而且从函数调用的任何调用中都是可见的。
请注意,这并不是递归所特有的。
$ X=3
$ foo () { local X=5; bar; }
$ bar () { echo $X; }
$ bar
3
$ foo
5
$ echo $X
3发布于 2017-04-06 05:53:32
让函数变得更详细,只需使用4作为限制。
你可以用6试试。
小心出口!!
#!/bin/bash
depth=0
f() {
echo "depth =======$((++depth))"
echo "Received $X"
local X=$X;
while (( X < 4 )); do
(( X++ ));
echo "Calling with $X";
#sleep 1;
f;
done;
echo "exit with $X depth $((depth--))"
}
X=1
f
echo "final depth is $depth"运行它将准确地显示所发生的事情:
$ ./script
depth =======1
Received 1
Calling with 2
depth =======2
Received 2
Calling with 3
depth =======3
Received 3
Calling with 4
depth =======4
Received 4
exit with 4 depth 4
exit with 4 depth 3
Calling with 4
depth =======3
Received 4
exit with 4 depth 3
exit with 4 depth 2
Calling with 3
depth =======2
Received 3
Calling with 4
depth =======3
Received 4
exit with 4 depth 3
exit with 4 depth 2
Calling with 4
depth =======2
Received 4
exit with 4 depth 2
exit with 4 depth 1
final depth is 0https://stackoverflow.com/questions/43239895
复制相似问题