我有一个关于 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
我不确定你想做什么,但是
- 你永远不会
return 0
从函数中(“true”),所以它会绝不返回,直到尝试完所有组合。 $i
是不是局部变量:$ foo() { i=1; bar; } $ bar() { echo $i; } $ foo 1
您可能想通过查看每个命令位于哪一行来进行调试:
trap 'printf "$LINENO "' DEBUG
$1
是每个本地的函数调用,并且即使函数调用自身也不会延续:$ foo() { if [ $# -ne 0 ]; then echo "One more time"; foo; fi; } $ foo 1 One more time
每种主要的高级编程语言都是如此。否则,递归将被彻底破坏。