0
#!/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

In the code above the range of the outer loop is interpreted as wanted, iterating from 2 to 4. Both substitutions in the range of the inner loop also work. However the inner range is interpreted as a string and not a range of integers. How can I fix this issue?

Expected:

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

Result:

{1..3}
{1..5}
{1..7}
ilkkachu
  • 138,973

1 Answers1

0

In bash, brace expansion is done before other expansion, and you can't use expansion inside them. That's one of the most frequently asked questions here.

Though you could use another shell like zsh (where {x..y} comes from) or ksh93 or yash -o braceexpand to work around the problem, in general you don't want to use brace expansion in for loops as doing for i in {1..1000000} for instance involves storing the full list of numbers in memory several times for no good reason. It's almost as bad as using for i in $(seq 1000000).

You'd rather use the C-like loops from ksh93:

#! /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

I also removed the split+glob invocation in your code which made no sense.

Switching to zsh would have other advantages. For instance, the code above could look like:

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

Or:

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