首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Bash-4递归的奇数结果

Bash-4递归的奇数结果
EN

Stack Overflow用户
提问于 2017-04-05 19:21:44
回答 3查看 60关注 0票数 1

我设计了一个简单的测试来查看Bash如何使用递归操作,但我不理解结果。

测试:

  1. 在shell中分配一个全局变量X
  2. 创建一个函数f(),该函数分配同名的变量local X
  3. local X分配全局X的值,即local X=$X
  4. 递归此函数几次,并检查在每个递归中,它是使用全局X还是使用上一轮函数中的local X

我期望两种结果中的一种:

  • 对于每个递归,来自上一个local Xf()将是新的“全局”X,即下一个向上作用域中的X,这将指示每个递归在前一个作用域下创建一个新的范围。
  • 在每次递归时,都会忘记以前的local X值,而每个新的local X=$X将简单地重新分配我最初分配的全局X的值。这表明Bash创建了相邻的作用域。

我没有收到任何这些。我有奇怪的东西。下面是来自终端的复制粘贴。

我在shell中赋值一个全局变量:

代码语言:javascript
复制
user@ubuntu-zesty:~$ X=1

我在shell中创建一个函数f(),该函数创建local X,将全局X的值赋值给它,进入一个while循环,将1添加到local X (假设它是本地的),打印新的local X值,并调用自己。重复5或6次。

代码语言:javascript
复制
user@ubuntu-zesty:~$ f() { local X=$X; while [ $X -lt 6 ]; do X=$(( $X + 1 )); echo $X; sleep 1; f; done; }

然后我调用f(),输出就是令人费解的。

代码语言:javascript
复制
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没有受到影响。

代码语言:javascript
复制
user@ubuntu-zesty:~$ echo $X
1

这是怎么回事?它有时使用全局X,有时使用local X?如果你知道这里发生了什么,请不要放过我血淋淋的细节。

最后,为了好玩,输出的图表:

代码语言:javascript
复制
 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 ======

规格:

  • Bash-4.4.5(1)-release
  • x86_64 UbuntuZ校
  • Linux内核4.10.0-17-泛型
  • VMware工作站12虚拟机
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-04-05 20:11:14

我认为,如@chepner在其回答中所解释的那样,可视化动态范围的最佳方法是稍微修改您的功能:

代码语言:javascript
复制
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
}

并查看值是如何增加的:如果遵循输出列,则可以调试每个级别发生的情况。

代码语言:javascript
复制
$ 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
...
票数 2
EN

Stack Overflow用户

发布于 2017-04-05 19:58:02

bash是动态作用域,而不是静态作用域(也称为词汇范围)。这意味着在执行行local X=$X时,并不是根据在全局词法作用域分配的值来获得$X的值,而是基于最近的运行时作用域中存在的值,即调用f的作用域中的值。这意味着一个局部值不仅在函数调用中可见,而且从函数调用的任何调用中都是可见的。

请注意,这并不是递归所特有的。

代码语言:javascript
复制
$ X=3
$ foo () { local X=5; bar; }
$ bar () { echo $X; }
$ bar
3
$ foo
5
$ echo $X
3
票数 2
EN

Stack Overflow用户

发布于 2017-04-06 05:53:32

让函数变得更详细,只需使用4作为限制。

你可以用6试试。

小心出口!!

代码语言:javascript
复制
#!/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"

运行它将准确地显示所发生的事情:

代码语言:javascript
复制
$ ./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 0
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43239895

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档