Why is `for i in {1..10}` different from `for ((i=1; i<=10; i++))`?

Viewed 362

I wrote a simple code via bash script,

Code 1

for((i=1;i<=10;i++))
do
        echo $i 
        i=$((i+1))
        echo $i
        i=$((i+2))
done

output of Code 1

1
2
5
6
9
10

Code 2

for i in {1..10}
do
        echo $i 
        i=$((i+1))
        echo $i
        i=$((i+2))
done

output of Code 2

1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
10
10
11

I'm just wondering, why outputs are not same ?
Thnx in advance

3 Answers

With in, the variable iterates over the list. You can change its value in the loop, but when the next iteration starts, the next value will be assigned to it, regardless of what value you assigned to it. (And I can't imagine any other behaviour: should the shell try to guess how far in the list you want to jump? What if the value is repeated, or not present in the list at all?)

With the C-style for, the variable is initialized, and at each iteration, its value is changed and the condition checked. There's no list of values, only the condition to end the loop.

These are not shorthand for each other: They're completely different code, and expected to behave in different ways.

{1..10} is just shorthand for 1 2 3 4 5 6 7 8 9 10; when you run for i in 1 2 3 4 5 6 7 8 9 10, you're explicitly assigning those exact values to i in turn, overwriting whatever else was previously there.

By contrast, for ((i=1; i<=10; i++)) is providing three separate statements: An initializer (i=1), telling it what to do to start the loop; a check (i<=10) to tell it how to determine whether the loop is finished; and an update (i++), telling it what to do between loop iterations. These are completely arbitrary commands, and you can put any arithmetic expression you want in these positions.

The for((i=1;i<=10;i++)) loop could be rewritten as such:

i=1                              # for loop's 'i=1'

while [[ "${i}" -le 10 ]]        # for loop's 'i<=10'
do
        echo $i
        i=$((i+1))
        echo $i
        i=$((i+2))
        ((i++))                  # for loop's 'i++'
done

This generates ... you guessed it ...

1
2
5
6
9
10

Charles Duffy has already expanded the for i in {1..10} loop to show how that behaves.

Related