# How to combine arithmetic expansion and brace expansion? [duplicate]

Can peoples combine arithmetic expansion and brace expansion?

``````\$ for i in {\$((1 + 1))..5}; do echo \$i; done;
{2..5}
\$ echo "bash laughs at me"
``````

## marked as duplicate by jordanm, Mikel, cuonglm, Networker, polymAug 27 '14 at 16:58

• @jordanm - This seems slightly different than the duplicate you identified. The dup just shows brace expansions in a for loop, this is asking how to do arthmetic expansion inside a brace expansion. – slm Aug 27 '14 at 15:57

See `man bash` for explanation:

The order of expansions is: brace expansion, tilde expansion, parameter, variable and arithmetic expansion and command substitution (done in a left-to-right fashion), word splitting, and pathname expansion.

Brace expansion happens before arithmetic expansion, so you can't combine them in the way you tried.

Use `seq` instead:

``````for i in \$(seq \$((a+4)) 12) ; do echo \$i ; done
``````
``````eval 'for i in {'"\$((1 + 1))"'..5}; do echo \$i; done'
``````

### OUTPUT

``````2
3
4
5
``````

In general if you want the shell to do something before it actually does, you have to give the shell a second look at it. This is `eval`'s function - it twice-evaluates a command. The shell parses its evaluation of shell expansions - which generally does not happen.

Consider this:

``````v='"quotes in here"'; printf %s\\n \$v
"quotes
in
here"
``````

You see the quotes are interpreted by the shell's parser, which handles the input before expansions are made, and so the quotes within `\$v` have no meaning there - there is no parser to understand them. But if I do:

``````v='"quotes in here"'; eval "printf '%s\\n' \$v"
quotes in here
``````

The output is suddenly different. The difference is made by the parser - it's the bit that decides what bits of its input are commands and why. It's the part that works with `;\${}()||''""&& while for if` all of that kind of stuff. That doesn't mean that the `{}` braces back there are equivalent to the ones you're asking about - as the other answer has already shown, those are apparently handled separately as a `bash` extension. In any case, generally you need some form of second evaluation to handle this.

It is this that makes `eval` dangerous. When you `"\${expansion}"` quote an expansion you mark it for the parser - you delimit it. The shell knows that, whatever happens, that is but one item - likely an argument - in a command. And even when you don't; the shell will not accept an `\$expansion` that falls outside a `;` simple command boundary - because that simple command is also already delimited. But - as it does with `eval` - if the shell were to come back and look at that expansion once more, it might find a command it can run - even several - and this is how `eval` works.

So when using `eval` you have to be very careful that you do not unexpectedly twice evaluate a shell token or any expansion that might contain one - and you only evaluate on the first go-round the part that the shell does not do soon enough otherwise. Best practice is only to singly evaluate any one part of the command, but at different times, as is done below.

Here's that first `eval` string again:

``````eval \                    #inital command
'for i in {'\             #hard-quoted - not expanded or executed
"\$((1 + 1))"\             #double-quoted - expanded and delimited
'..5}; do echo \$i; done'  #hard-quoted - not expanded or executed
``````

The comments above discuss the actions taken during `eval`'s inital pass - there is one more to go. In this case, you want `1+1`. So we first expand that and nothing else. The worst that we can get out of that is `2`. This is not a shell parser token and it is safe to evaluate - and is even double-quoted. In fact, if there is any real valid use of `eval` it is arithmetic. Everything else is hard-quoted - there is no action taken and the strings are simply concatenated and the quotes removed, as would happen with any other hard-quoted string.

But when it comes back the second time - after the quotes are removed from the first pass - the shell finds:

``````for i in {2..5}; do echo \$i; done
``````

And it does it.

``````bash -c "for i in {\$((1+1))..5}; do echo \\$i; done"
``````

^that works.

And:

``````. /dev/fd/0 <<CMD
for i in {\$((1+1))..5}; do echo \\$i; done
CMD
``````

^that works. In every case the logistics are the same - you evaluate the variable before you evaluate the `bash` brace expansion.

I've never had a lot of use for the brace expansion myself, though. I usually do like:

``````until [ \$((i=\$i+1)) -gt 5 ]
do  printf %d\\n \$i
done
``````