bash - bash如何循环访问一个变量所定义的数字范围?

  显示原文与译文双语对照的内容

当范围由变量给出时,如何迭代bash中的一系列数字?

我知道我可以执行( 调用名"序列表达式"在 bash 文档编辑器中):


 for i in {1..5}; do echo $i; done

这给出了:

1
2
3
4
5

但是,如何将一个范围端点替换为一个变量? 这不起作用:


END=5
for i in {1..$END}; do echo $i; done

哪些指纹:

%7B1..5%7D

时间:

讨论

使用 seq 很好,因为Jiaaro建议。 Pax Diablo建议了一个bash循环,以避免调用子进程,如果 $END 太大的话,它还具有更多内存友好的优势。 Zathrus在循环实现中发现了一个典型的Bug,并且还暗示,由于i 是一个文本变量,连续转换to-and-fro数字是用相关的slow-down执行的。

整数算术

这是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 ( 就像我在ksh手册页上做的那样,这是很久以前的事情了)的整个手册页,我错过了。

那么,


typeset -i i END # let's be explicit
for ((i=1;i<=END;++i)); do echo $i; done

看起来是最 memory-efficient ( 没有必要分配内存来消耗 seq 输出,如果结束非常大,这可能是一个问题) 方式,虽然"最快"应该不要了。

最初的问题

eschercycle注意到,{ 。 b } bash表示法只能处理字面值;真,与之相适应的bash手册。 单个( 内部) fork() 不带 exec()的方法可以克服这个 obstacle:


for i in $(eval echo"{1..$END}"); do

于命令替代作用同时 evalecho bash内置的,而是一个相关 fork() 注册号。

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)); 构造类似于 for (expr1;expr2;expr3) 中的和类似的语言,类似于其他 ((expr)) 案例,Bash把它们当作算术。

我知道这问题是关于 bash,但仅就档案- ksh93 是按预期的智能,实现它:


$ ksh -c 'i=5; for x in {1..$i}; do echo"$x"; done'
1
2
3
4
5
$ ksh -c 'echo $KSH_VERSION'
Version JM 93u+ 2012-02-29

$ bash -c 'i=5; for x in {1..$i}; do echo"$x"; done'
{1..5}

这些都很好,但seq被认为是不推荐使用的,并且只能使用数字范围。

如果将for循环enclose括在双引号中,那么当你回显字符串时,开始和结束变量将被取消引用,并且你可以将字符串直接返回到BASH以便执行。 $i 需要用 's 转义,因此在发送到子shell之前它不会被评估。


RANGE_START=a
RANGE_END=z
echo -e"for i in {$RANGE_START..$RANGE_END}; do echo ${i}; done" | bash

这个输出也可以分配给一个变量:


VAR=`echo -e"for i in {$RANGE_START..$RANGE_END}; do echo ${i}; done" | bash`

应该生成的唯一"高架"应该是bash的第二个实例,因此它应该适合密集的操作。

...