72

Is it possible to do something like this:

start=1
end=10
echo {$start..$end}
# Ouput: {1..10}
# Expected: 1 2 3 ... 10 (echo {1..10})
Tyilo
  • 28,998
  • 40
  • 113
  • 198

7 Answers7

72

In bash, brace expansion happens before variable expansion, so this is not directly possible.

Instead, use an arithmetic for loop:

start=1
end=10
for ((i=start; i<=end; i++))
do
   echo "i: $i"
done

OUTPUT

i: 1
i: 2
i: 3
i: 4
i: 5
i: 6
i: 7
i: 8
i: 9
i: 10
that other guy
  • 116,971
  • 11
  • 170
  • 194
anubhava
  • 761,203
  • 64
  • 569
  • 643
  • 1
    and should output be 1 2 3 4 5 6 7 8 9 10? – philcolbourn Mar 08 '14 at 03:00
  • it's possible, but it is a little bit ugly because one starts another shell to do the variable expansion before the brace expansion: `start=1;end=10;for i in $(bash -c "echo {$start..$end}");do echo $i;done` – syss Mar 20 '18 at 13:37
29

You should consider using seq(1). You can also use eval:

eval echo {$start..$end}

And here is seq

seq -s' ' $start $end
cnicutar
  • 178,505
  • 25
  • 365
  • 392
10

You have to use eval:

eval echo {$start..$end}
bmk
  • 13,849
  • 5
  • 37
  • 46
  • 9
    That's like using a jackhammer to pound a nail. It's dangerous (literally, introduces potential shell injection vulnerabilities if any of your values come from untrusted inputs), and not the right tool for the job. `for ((i=start; i – Charles Duffy Sep 26 '13 at 20:17
9

If you don't have seq, you might want to stick with a plain for loop

for (( i=start; i<=end; i++ )); do printf "%d " $i; done; echo ""
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
2

I normally just do this:

echo `seq $start $end`
opsguy
  • 1,781
  • 1
  • 12
  • 11
  • Look at my comment to cnicutar's answer – Tyilo May 31 '11 at 17:30
  • `seq` is a non-standard tool (literally, not specified in POSIX). – Charles Duffy Sep 26 '13 at 20:18
  • 2
    Let alone the fact that `seq` is non-standard, but the echo + command substitution is just a silly combination. – ilkkachu May 16 '17 at 13:32
  • @ilkkachu not if you need to add a newline. – Bruno Bronosky Jan 29 '19 at 19:34
  • 1
    @BrunoBronosky, well, the bigger difference is that the unquoted command substitution folds the whitespace to single spaces (unless `IFS` is changed from the default). So you get the numbers all on the same line, not one line each like the default with `seq`. But if you want that, you could just use `seq -w ' ' 1 10`. If you do quote the command substitution, on the other hand, then `echo "$(seq 1 10)"` and `seq 1 10` have exactly the same output. Command substitution strips trailing newlines (there's one), and `echo` adds one back. – ilkkachu Jan 29 '19 at 19:48
2

Are you positive it has be BASH? ZSH handles this the way you want. This won't work in BASH because brace expansion happens before any other expansion type, such as variable expansion. So you will need to use an alternative method.

Any particular reason you need to combine brace and variable expansion? Perhaps a different approach to your problem will obviate the need for this.

Spencer Rathbun
  • 14,510
  • 6
  • 54
  • 73
1

use -s ex: seq -s ' ' 1 10 output: 1 2 3 4 5 6 7 8 9 10