shell中for循环控制变量的范围?

shell中for循环控制变量的范围?

我有一个关于 shell 中 for 循环的问题。

让我们假设这个简单的 shell 脚本:

#!/bin/sh
loop() {                                                                                                                                                                                                                                                                                                               
    for i in 1 2 3 4; do                                                                                                                                           
        if [ $i -eq 2 ]; then                                                                                                                                      
            [ $1 -eq 2 ] && return 1                                                                                                                           
            loop $(($1 + 1)) && return 1                                                                                                                     
        fi                                                                                                                                                         
    done                                                                                                                                                           
return 1                                                                                                                                                       
}                                                                                                                                                                  

loop 0       

除参数(和函数参数)外,所有变量都是全局变量。因此,如果我想要函数中的局部变量,我必须将其作为参数传递。

我尝试运行这个简单的脚本,但我不确定 for 循环列表(本例中为 1 2 3 4)是否也是本地的?见下文:

+ loop 0
+ for i in 1 2 3 4
+ '[' 1 -eq 2 ']'
+ for i in 1 2 3 4
+ '[' 2 -eq 2 ']'
+ '[' 0 -eq 2 ']'
+ loop 1
+ for i in 1 2 3 4
+ '[' 1 -eq 2 ']'
+ for i in 1 2 3 4
+ '[' 2 -eq 2 ']'
+ '[' 1 -eq 2 ']'
+ loop 2
+ for i in 1 2 3 4
+ '[' 1 -eq 2 ']'
+ for i in 1 2 3 4
+ '[' 2 -eq 2 ']'
+ '[' 2 -eq 2 ']'
+ return 1
+ for i in 1 2 3 4
+ '[' 3 -eq 2 ']'
+ for i in 1 2 3 4
+ '[' 4 -eq 2 ']'   <- here is $i == 4
+ return 1
+ for i in 1 2 3 4
+ '[' 3 -eq 2 ']'   <- here is $i == 3, correctly behaving as local variable ...
+ for i in 1 2 3 4
+ '[' 4 -eq 2 ']'
+ return 1

谁能告诉我 for 循环内部是如何工作的?我对 for 循环列表有点困惑,它的行为就像“局部变量”。

非常感谢您的所有回答! :)

答案1

$ reset() { i=$1; }
$ for i in 1 2 3 4 ; do echo -n "$i "; reset 3; echo "$i" ; done;
1 3
2 3
3 3
4 3

i不是local在 中进行的reset,因此其中的更改在函数外部可见。但 的更改不会影响后续迭代中获得的i值。命令i中列出的单词按预期一次按顺序for分配给一个单词。i

所以是的,有一个“隐藏指针”可以告诉单词列表中的位置。必须有,否则带有重复单词的循环(如 like)for i in a a a ; do ...将不起作用。每次迭代都会i得到相同的值,但循环仍然运行固定次数的迭代。

答案2

我不确定你想做什么,但是

  1. 你永远不会return 0从函数中(“true”),所以它会绝不返回,直到尝试完所有组合。
  2. $i不是局部变量:

    $ foo() { i=1; bar; }
    $ bar() { echo $i; }
    $ foo
    1
    
  3. 您可能想通过查看每个命令位于哪一行来进行调试:

    trap 'printf "$LINENO "' DEBUG
    
  4. $1是每个本地的函数调用,并且即使函数调用自身也不会延​​续:

    $ foo() { if [ $# -ne 0 ]; then echo "One more time"; foo; fi; }
    $ foo 1
    One more time
    

    每种主要的高级编程语言都是如此。否则,递归将被彻底破坏。

相关内容