当范围由变量给定时,如何在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}
当范围由变量给定时,如何在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}
当前回答
如果您使用BSD/OSX,您可以使用jot而不是seq:
for i in $(jot $END); do echo $i; done
其他回答
for i in $(seq 1 $END); do echo $i; done
编辑:比起其他方法,我更喜欢seq,因为我能记住它;)
另一层间接:
for i in $(eval echo {1..$END}); do
∶
这就是为什么最初的表达不起作用。
来自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吗?
如果你正在执行shell命令,并且你(像我一样)对流水线有着一种迷恋,那么这个命令很好:
seq 1$END | xargs-I{}echo}
这些都很好,但seq被认为是不可取的,而且大多数只适用于数字范围。
如果将for循环括在双引号中,则当回显字符串时,开始变量和结束变量将被取消引用,并且可以将字符串直接发送回BASH执行$我需要用\来转义,所以在被发送到子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的第二个实例,因此它应该适合密集型操作。