如何在Bash的for循环中使用变量

96
如何在Bash for循环中使用变量?如果我只是使用标准的for循环,它会按照我的期望工作。
for i in {0..3}
do
   echo "do some stuff $i"
done

这个很有效,它循环4次,从0到3(包括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循环的专家提供的帮助。


zsh 最适合这个 :-) - asgs
3个回答

165

有一种方法是使用 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

2
在双括号中引用变量时,可以省略 $ 符号。 - 4xy

20
在bash中,花括号展开是首先尝试的步骤,因此在那个时候,$length 不会被替换。
bash的man页面清晰地说明:
“序列表达式采用{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

9

花括号替换是在其它操作之前进行的,因此您需要使用 eval 或第三方工具如 seq

eval 的示例:

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

这些信息实际上可以在man bash中找到:
一个序列表达式的形式为{x..y[..incr]},其中x和y是整数或单个字符,incr是可选的增量,是一个整数。大括号展开在任何其他扩展之前执行,并且保留任何其他扩展特殊字符。它是严格文本性质的,在展开的上下文或大括号之间的文本中不应用任何语法解释。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接