当范围由变量给定时,如何在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

哪些打印:

{1..5}


当前回答

如果您不想使用“seq”或“eval”或jot或算术扩展格式,例如for((i=1;i<=END;i++)),或其他循环,例如while,并且您不想只使用“printf”和“echo”,那么这个简单的解决方法可能适合您的预算:

a=1;b=5;d=‘对于{‘$a‘..‘$b‘}中的i;do echo-n“$i”;完成;'echo“$d”|bash

PS:反正我的bash没有“seq”命令。

在Mac OSX 10.6.8、Bash 3.2.48上测试

其他回答

如果你需要前缀,你可能会喜欢这个

 for ((i=7;i<=12;i++)); do echo `printf "%2.0d\n" $i |sed "s/ /0/"`;done

这将产生

07
08
09
10
11
12

另一层间接:

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

您可以使用

for i in $(seq $END); do echo $i; done

如果你正在执行shell命令,并且你(像我一样)对流水线有着一种迷恋,那么这个命令很好:

seq 1$END | xargs-I{}echo}

这就是为什么最初的表达不起作用。

来自man bash:

在之前进行支撑扩展任何其他扩展,以及其他特殊字符扩展保留在后果它是严格的文本。猛击不应用任何语法对上下文的解释支撑。

因此,大括号扩展是在参数扩展之前作为纯文本宏操作完成的。

外壳是宏处理器和更正式的编程语言之间高度优化的混合体。为了优化典型用例,语言变得更加复杂,并且接受了一些限制。

正式建议

我建议坚持使用Posix1功能。这意味着在<list>中使用for i;如果列表已经知道,则使用while或seq,如:

#!/bin/sh

limit=4

i=1; while [ $i -le $limit ]; do
  echo $i
  i=$(($i + 1))
done
# Or -----------------------
for i in $(seq 1 $limit); do
  echo $i
done

1.Bash是一个很棒的shell,我以交互方式使用它,但我不会在脚本中使用Bash。脚本可能需要更快的外壳、更安全的外壳和更嵌入式的外壳。他们可能需要在任何安装为/bin/sh的设备上运行,然后就有了所有常见的支持标准的论点。还记得shellshock,又名bashtoor吗?