80

如何在 bash for 循环中使用变量?如果我只使用标准 for 循环,它会达到我的预期

for i in {0..3}
do
   echo "do some stuff $i"
done

这工作正常。它循环 4 次,包括 0 到 3 次,打印我的消息并将计数放在最后。

do some stuff 0
do some stuff 1
do some stuff 2
do some stuff 3

当我用下面的 for 循环尝试同样的事情时,它似乎等于一个字符串,这不是我想要的。

length=3
for i in {0..$length}
do
   echo "do something right $i"
done

输出:

do something right {0..3}

我试过了

for i in {0.."$length"} and for i in {0..${length}} (both output was {0..3})

for i in {0..'$length'} (output was {0..$length})

他们都没有做我需要的。希望有人可以帮助我。提前感谢任何 bash 专家对 for 循环的帮助。

4

3 回答 3

128

一种方法是使用eval

for i in $( eval echo {0..$length} )
do
       echo "do something right $i"
done

请注意length=;ls设置或时会发生什么length=; rm *(尽管不要尝试后者)。

安全地,使用seq

for i in $( seq 0 $length )
do
       echo "do something right $i"
done

或者您可以使用 c 风格的 for 循环,这也是安全的:

for (( i = 0; i <= $length; i++ )) 
do 
       echo "do something right $i"
done
于 2013-06-19T02:07:44.913 回答
15

在 bash 中,大括号扩展是尝试的第一步,因此此时$length不会被替换。

bash 的联机帮助页清楚地指出:

序列表达式采用 {x..y[..incr]} 的形式,其中 x 和 y 是整数或单个字符...

有多种可能性,例如使用:

pax> for i in $(seq 0 $length) ; do echo $i ; done
0
1
2
3

虽然如果很大的话,这可能会给你一个很大的命令行length

另一种选择是使用类似 C 的语法:

pax> for (( i = 0; i <= $length; i++ )) ; do echo $i; done
0
1
2
3

也可以省略双括号$中的符号来引用变量:

ubuntu@ip-172-31-28-53:~/playground$ length=3;
ubuntu@ip-172-31-28-53:~/playground$ for ((i=0;i<=length;i++));do echo $i;done
0
1
2
3
于 2013-06-19T02:09:27.400 回答
7

大括号替换在任何其他替换之前执行,因此您需要使用eval或第三方工具,如seq.

评估示例:

for i in `eval echo {0..$length}`; do echo $i; done

此信息实际上可以在以下位置找到man bash

序列表达式采用 {x..y[..incr]} 的形式,其中 x 和 y 是整数或单个字符,而 incr(可选增量)是整数。[...]

大括号扩展在任何其他扩展之前执行,并且任何其他扩展的特殊字符都保留在结果中。 它是严格的文本。Bash 不对扩展的上下文或大括号之间的文本应用任何句法解释。

于 2013-06-19T02:12:19.707 回答