3

So I was writing a for loop and getting some errors, to get an understanding of the errors I wrote this

    #! /bin/bash
    b=${1:- 10}
    echo $b
    for i in {0..$b}
    do
            echo "$i"
    done

so if I run ./forloop.sh 10

I get

    10
    {0..10}

why doesn't the range work when I have a variable as the second argument?

Jake Schievink
  • 409
  • 4
  • 16

3 Answers3

5

Bash doesn't expand the range. Use this instead.

for (( i=0; i<=$b; i++)) 
FDinoff
  • 30,689
  • 5
  • 75
  • 96
2

The part of bash that expands things like {1..10} into 1 2 3 4 5 6 7 8 9 10 runs before any parameters like $b are replaced by their values. Since {1..$b} doesn't look like a numeric range, it doesn't get expanded. By the time parameter expansion turns it into {1..10}, it's too late; nothing is going to come along and evaluate the curly-brace expression.

Mark Reed
  • 91,912
  • 16
  • 138
  • 175
  • Do you know why it does this? – Jake Schievink May 16 '13 at 03:02
  • 3
    There has to be some order. The order in which the shell does this is well established and well documented. Read the Bash manual page for the nittty gritty. It doesn't have a rationale, but when you see how many different substitution mechanisms there are in the shell, I think you'll agree at least that there has to be an order. Fundamentally, it's just arbitrary. – tripleee May 16 '13 at 03:47
  • What's the alternative, @JakeSchievink? If the shell went back and kept expanding things as long as anything looked expandable, you'd run into unpredictable results and lots of infinite recursion. – Mark Reed May 16 '13 at 03:55
1

Change the script to use the following (http://ideone.com/MwAi16).

b=10 
for i in $(eval echo {0..$b})
Bill
  • 5,263
  • 6
  • 35
  • 50
  • 2
    Don't use `eval` if you can at all avoid it. If the source of `$b` is even a little more remote than the immediately-prior assignment here, it's far too easy to wind up with code doing completely unexpected things. – Mark Reed May 16 '13 at 02:40
  • @MarkReed Agreed. But the OP's question was about `{0..$b}`, and `eval` is just a way to solve it. There are numerous ways to write a loop, and it is just a solution. I do not see the reason for the down vote though. – Bill May 16 '13 at 02:41
  • 2
    @Bill Mark is simply pointing out that the `eval` can possibly be a security threat au should by avoided. Also your solution can be replaced with this: `b=10; for i in $(seq 0 $b); do echo $i; done`. No needs for the `eval`. eval is evil. – Lynch May 16 '13 at 04:40