1

I am new to Unix programming and I am not able to figure out what is wrong with this code:

#!/bin/sh
    i=1
    max=10
        for i in {1..$max}
        do
            echo $i;
        done

If I try the above code as follows it works:

#!/bin/sh
    i=1
    max=10
        for i in {1..10}
        do
            echo $i;
        done

I have tried this:

#!/bin/sh
    i=1
    max=10
        for i in {1..`echo $max`}
        do
            echo $i;
        done

and

#!/bin/sh
    i=1
    max=10
        for i in {1..`expr $max`}
        do
            echo $i;
        done

and

#!/bin/sh
    i=1
    max=10
        for i in {1..`echo $max | bc`}
        do
            echo $i;
        done

But it is also not working.. Can anyone tell me how come it will work..?

Veer Shrivastav
  • 5,434
  • 11
  • 53
  • 83

4 Answers4

3

Bash/zsh support much more faster and flexible form:

for ((i=1; i<$max; ++i));

Don't use external commands (like seq), or backticks - it will slow down your script.

Leonid Volnitsky
  • 8,854
  • 5
  • 38
  • 53
2

Maybe you can try this

#!/bin/sh
max=10
for i in $(seq 1 $max)
do
    echo "$i"
done

You can see this answer

brace expansion, {x..y} is performed before other expansions, so you cannot use that for variable length sequences.

Update:

In the case of you want a sequence of custom increment, the man page of seq gives the following:

seq [-w] [-f format] [-s string] [-t string] [first [incr]] last

Therefore you can use seq 1 3 $max to get a sequence with increment 3.

In general,

#!/bin/sh
max=10
incr=3
for i in $(seq 1 $incr $max)
do
    echo "$i"
done
Community
  • 1
  • 1
lazywei
  • 11,955
  • 5
  • 20
  • 25
1

Sequence expressions of the form {x..y} only take place when x and y are literal numbers or single characters. It takes place before variable expansion. If the limits can include variables, use the seq command:

for i in $(seq 1 $max)
Barmar
  • 741,623
  • 53
  • 500
  • 612
1

The bash man page says this:

Brace expansion is performed before any other expansions, and any characters special to other expansions are preserved in the result. It is strictly tex- tual. Bash does not apply any syntactic interpretation to the context of the expansion or the text between the braces.

So it appears that bash just passes through verbatim whatever text is in the braces. I wasn't familiar with that syntax, and I had to look it up. It doesn't sound like it was intended to be used in for loops.

bash has newer ways of doing this, but the traditional way is

for i in $(seq 1 $max)
do
 # whatever...
done

Since pretty much anything can be done in bash with enough effort, and I couldn't turn down the challenge, here's how you could do it with braces anyway:

for i in $(eval echo {1..$max})
do
 echo $i
done