如何在 bash for 循环中使用变量

如何在 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 循环的帮助。

104120 次浏览

One way is using eval:

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

Note what happens when you set length=;ls or length=; rm * (don't try the latter though).

safely, using seq:

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

or you can use the c-style for loop, which is also safe:

for (( i = 0; i <= $length; i++ ))
do
echo "do something right $i"
done

In bash, brace expansion is the first step attempted so, at that point, $length will not have been substituted.

The manpage for bash states clearly:

A sequence expression takes the form {x..y[..incr]}, where x and y are either integers or single characters ...

There are a number of possibilities, such as using:

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

though that may give you a large command line if length is massive.

Another alternative is to use the C-like syntax:

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

It's also possible to omit $ sign in double parentheses to refer a variable:

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

Brace subtitutions are performed before any other, so you need to use eval or a third-party tool like seq.

Example for eval:

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

This information can actually be found in man bash:

A sequence expression takes the form {x..y[..incr]}, where x and y are either integers or single characters, and incr, an optional increment, is an integer. [...]

Brace expansion is performed before any other expansions, and any characters special to other expansions are preserved in the result. It is strictly textual. Bash does not apply any syntactic interpretation to the context of the expansion or the text between the braces.