如何遍历Bash中由变量定义的一系列数字?
当范围由变量给出时,如何迭代Bash中的一系列数字?
我知道我可以做到这一点(在Bash文档中称为“序列表达式”):
for i in {1..5}; do echo $i; done
这使:
1
2
3
4
五
然而,我怎样才能用变量替换范围端点? 这不起作用:
END=5
for i in {1..$END}; do echo $i; done
打印:
{} 1..5
for i in $(seq 1 $END); do echo $i; done
编辑:我更喜欢seq
在其他方法,因为我实际上可以记住它;)
seq
方法是最简单的,但Bash具有内置的算术评估。
END=5
for ((i=1;i<=END;i++)); do
echo $i
done
# ==> outputs 1 2 3 4 5 on separate lines
for ((expr1;expr2;expr3));
像C语言和类似语言中的for (expr1;expr2;expr3)
一样构造工作,和其他((expr))
情况一样,Bash将它们视为算术。
讨论
正如Jiaaro所说,使用seq
很好。 Pax Diablo提出了一个Bash循环来避免调用一个子进程,如果$ END太大,还有更多的内存友好。 Zathrus在循环实现中发现了一个典型的错误,并且暗示说由于i
是一个文本变量,所以连续转换来回数字时会执行相关的减速操作。
整数算术
这是Bash循环的改进版本:
typeset -i i END
let END=5 i=1
while ((i<=END)); do
echo $i
…
let i++
done
如果我们想要的唯一的东西是echo
,那么我们可以编写echo $((i++))
。
ephemient教会了我一些东西:Bash允许for ((expr;expr;expr))
构造。 由于我从来没有阅读Bash的整个手册页(就像我用Korn shell( ksh
)手册页完成的那样),但我错过了这一点。
所以,
typeset -i i END # Let's be explicit
for ((i=1;i<=END;++i)); do echo $i; done
似乎是最具有内存效率的方式(不需要分配内存来消耗seq
的输出,如果END非常大,这可能会成为问题),尽管可能不是“最快”的。
最初的问题
eschercycle指出{a..b} Bash符号只适用于文字; 真实的,因此Bash手册。 可以用一个没有exec()
的单一(内部) fork()
来克服这个障碍(就像调用seq
,这是另一个图像需要fork + exec一样):
for i in $(eval echo "{1..$END}"); do
eval
和echo
都是Bash buildins,但是命令替换( $(…)
构造)需要fork()
)。
上一篇: How do I iterate over a range of numbers defined by variables in Bash?