Shell脚本中使用变量作为for循环范围

服务器

浏览数:74

2019-10-13

AD:资源代下载服务

我们知道在shell脚本中,可以通过{x..y}这样的表达式来表示一个从x到y的数列

echo {1..10}
1 2 3 4 5 6 7 8 9 10

这个用法在shell脚本里叫做Brace Expansion

因此我们常利用这个表达式来作为循环的次数,如:

for i in {1..10}
do
    echo "$i"
done

可以得到从1到10的输出结果。

但是如果我们想输出从1到一个变量的结果,这个变量从其他地方获取:

NUM=10
for i in {1..$NUM}
do
    echo "$i"
done

得到的结果却是

{1..10}

先说解决方案

放弃使用{x..y}这样的表达式:

NUM=10
for i in $(seq 1 $NUM)
do
    echo "$i"
done

原理

seq命令的原理就不说了,这里说说为什么不能在{ }中使用变量。其实原因写在bash的man手册中:

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.

大意是说,Bash中会最先展开{ }中的内容,这个时候$NUM还不会被具体的值替代,所以是i在循环中读取的是‘{1..$NUM}’的一个完整的字符串,输出时$NUM会被10替代,就有了'{1..10}'这样的结果。

关于Bash中的展开 (expansion) 顺序,其实有不少值得注意的地方,一不留神可能就会踩坑,还是老前辈那句:脚本猛于虎。

作者:Aaaaaaaron