Bash - 当两端之一是变量时,范围不再按需要工作

Bash - 当两端之一是变量时,范围不再按需要工作
#!/bin/bash
myfirstarray=(1 3 5 7 9 11)
for i in {2..4}
    do
    for j in {1..${myfirstarray[$((i-1))]}}
        do
            echo ${j}
        done
    done

在上面的代码中,外循环的范围被解释为所需的,从 到2迭代4。内循环范围内的两种替换也都有效。但是,内部范围被解释为字符串而不是整数范围。我该如何解决这个问题?

预期的:

1
2
3
1
2
3
4
5
1
2
3
4
5
6
7

结果:

{1..3}
{1..5}
{1..7}

答案1

在 bash 中,大括号扩展是在其他扩展之前完成的,并且您不能在其中使用扩展。这是这里最常见的问题之一。

虽然您可以使用另一个像zsh(where {x..y}comes from) 或ksh93or 之类的 shellyash -o braceexpand来解决该问题,但通常您不想在for循环中使用大括号扩展,因为for i in {1..1000000}例如涉及将完整的数字列表多次存储在内存中好理由。它几乎和使用一样糟糕for i in $(seq 1000000)

您更愿意使用 ksh93 中的类似 C 的循环:

#! /bin/bash -
myfirstarray=(1 3 5 7 9 11)
for (( i = 2; i <= 4; i++ )); do
  for (( j = 1; j <= myfirstarray[i-1]; j++ )); do
     echo "$j"
  done
done

我还删除了代码中没有意义的 split+glob 调用。

切换到 zsh 还有其他优势。例如,上面的代码可能如下所示:

#! /bin/zsh -
myfirstarray=(1 3 5 7 9 11)
for i ({2..4}) for j ({1..$myfirstarray[i]}) echo $j

或者:

#! /bin/zsh -
myfirstarray=(1 3 5 7 9 11)
for i ($myfirstarray[2,4]) for j ({1..$i}) echo $j

相关内容