Bash for循环语法

Bash for循环语法,bash,shell,for-loop,Bash,Shell,For Loop,我正在努力适应shell脚本,遇到了一个我觉得有趣且无法解释的行为。在下面的代码中,第一个for循环将正确执行,但第二个for循环不会正确执行 declare letters=(a b c d e f g) for i in {0..7}; do echo ${letters[i]} done for i in {0..${#letters[*]}}; do echo ${letters[i]} done 第二个for循环导致以下错误: syntax error: operand ex

我正在努力适应shell脚本,遇到了一个我觉得有趣且无法解释的行为。在下面的代码中,第一个for循环将正确执行,但第二个for循环不会正确执行

declare letters=(a b c d e f g)
for i in {0..7}; do
  echo ${letters[i]}
done
for i in {0..${#letters[*]}}; do
  echo ${letters[i]}
done
第二个for循环导致以下错误:

syntax error: operand expected (error token is "{0..7}")
让我困惑的是${letters[*]}显然被正确地计算为数字7。但是尽管如此,代码还是失败了,尽管我们刚刚看到使用{0..7}的同一个循环工作得非常好

这是什么原因


我正在运行OS X 10.12.2,GNU bash版本3.2.57。

括号展开发生在参数展开之前参见man bash中的展开,因此它仅适用于文本。换句话说,不能对变量使用大括号展开

您可以使用C样式的循环:

for ((i=0; i<${#letters[@]}; i++)) ; do
    echo ${letters[i]}
done
但是你通常不需要索引,而是在元素本身上循环,见下面@TomFenech的答案。他还展示了获取索引列表的另一种方法


请注意,它应该是{0..6},而不是7。

括号展开发生在参数展开之前请参见man bash中的展开,因此它仅适用于文本。换句话说,不能对变量使用大括号展开

您可以使用C样式的循环:

for ((i=0; i<${#letters[@]}; i++)) ; do
    echo ${letters[i]}
done
但是你通常不需要索引,而是在元素本身上循环,见下面@TomFenech的答案。他还展示了获取索引列表的另一种方法


请注意,它应该是{0..6},而不是7。

大括号展开发生在参数展开之前,因此不能将变量用作范围的一部分

将数组展开为值列表:

for letter in "${letters[@]}"; do
    echo "$letter"
done
或者,将数组的索引展开到列表中:

for i in ${!letters[@]}; do 
    echo "${letters[i]}"
done

正如在评论中提到的,这两种方法也适用于稀疏阵列;不能总是假定数组为0到${letters[@]}之间的每个索引定义了一个值。

大括号展开发生在参数展开之前,因此不能将变量用作范围的一部分

将数组展开为值列表:

for letter in "${letters[@]}"; do
    echo "$letter"
done
或者,将数组的索引展开到列表中:

for i in ${!letters[@]}; do 
    echo "${letters[i]}"
done

正如在评论中提到的,这两种方法也适用于稀疏阵列;您不能总是假定数组为0到${letters[@]}之间的每个索引定义一个值。

对此的解释不清楚,但当您使用{0..7}时,它会扩展到1 2 3 4 5。。。等等,但是当你使用{0..${letters[*]}时,它会扩展为一个字符串{0..7},你不能对它进行迭代,不确定它的解释,但是当你使用{0..7}时,它会扩展为1 2 3 4 5…等等,但是当你使用{0..${letters[*]}时,它会扩展为一个字符串{0..7}您无法在这些上迭代的属性也适用于稀疏数组;您不能总是假设数组为0到${letters[@]}之间的每个索引定义一个值。这些属性也适用于稀疏数组;您不能总是假设数组为0到${letters[@]}之间的每个索引定义一个值。