6

In response to a comment of mine to this question on SF the OP asserts that the

for i in {1..$NUM}

expands correctly in bash. I have access to bash 4.0.33 (Ubuntu), 3.2.25 (Centos) and 3.00.16(1) (solaris 10). None of these will expand the {1..$NUM}.

Does anyone know which versions of bash do the expansion? If it's not bash what is it ? I know zsh will do the expansion but in the OP's script the shebang should remove the possibility of an alias ?

  • This is a duplicate of http://unix.stackexchange.com/questions/7738/how-can-i-use-var-in-a-shell-brace-expansion-of-a-sequence – mattdm Feb 24 '11 at 18:27
  • @mattdm: It's not. I read that before I posted the question. Please read my question carefully it is not about how to do it it's about how the OP can say their bash does it. –  Feb 24 '11 at 18:30
  • @Iain: that is puzzling. In that case, I'd recommend rewording the title of this question to make that clear (notice that the two answers you've gotten already also missed your point). – mattdm Feb 24 '11 at 18:36
  • @mattdm: Perhaps you're right but reading the title isn't the same as reading the question. –  Feb 24 '11 at 18:39
  • @Iain: but once you've read the title, you're primed to read the question a certain way. So, ya want answers or not? – mattdm Feb 24 '11 at 18:46
  • FWIW, bash 4.1.7 and bash 4.2.0, from various versions of Fedora, act the way you and I expect. – mattdm Feb 24 '11 at 18:47
  • 2
    Count me as one more thinking either Boban isn't showing his actual script or he's running it with ksh and zsh (both expand {1..$NUM} to 1 2 3 4 …). – Gilles 'SO- stop being evil' Feb 24 '11 at 19:46

3 Answers3

4

I'm pretty sure the person asking the question on server fault is wrong. They're either leaving out some detail intentionally or are unaware of some weird configuration on the machine (/bin/bash as a link to something else). I tried on the two-week-old bash 4.2 release, on bash 3.2 from CentOS 5, and on bash 2.05a (from 2001) which I built myself just now to try.

The oldest source on ftp.gnu.org is 1.14, but that doesn't build cleanly, and I'm not sure trying it is worthwhile. The documentation for that release contains the exact same key phrases as in the modern documentation:

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

But actually, now that I think of it, that's pointless, since the "{x..y}" syntax was added in bash 3.0, making looking before that useless.

So, let me try 3.0 ... right. Same behavior.

So yeah. I'm extremely skeptical. Something doesn't add up.


(Later...)

Aha! The server-fault questioner admits "Sorry. my mistake. I've put for actual number in i in {1..10}, so it worked well." So, there ya go.

The answer to this question is "no version of bash works like that". :)

mattdm
  • 40,245
  • I was beginning to wonder if it was some weird version of bash on OSX or something. –  Feb 25 '11 at 17:02
3

To expand this you'd have to use eval:

$ echo {1..5}
1 2 3 4 5
$ NUM=5
$ echo {1..$NUM}
{1..5}
$ eval "echo {1..$NUM}"
1 2 3 4 5

Be very, very careful with eval though! Make sure you check that it's really a number before you execute something like this if you're accepting user input. As my colleague observed: "eval is evil!"

l0b0
  • 51,350
  • Thanks, I'm actually trying to find out how it is that the OP in the linked question can assert that their bash expands {1..$NUM} into the sequence 1 2 3 ...NUM. –  Feb 24 '11 at 17:08
  • risky is not the same as evil. eval (and in general the ability to take some string or text and treat it as code) is powerful (just take a look at Lisp and all the amazing stuff you can do with it or languages that borrow from it!) – iconoclast Jul 14 '11 at 20:14
2

Brace expansion does not expand variables, because the brace expansion is the very first step of the shell expansion and the variables are expanded later.

From the bash man page:

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

So:

NUM=4
for i in {1..$NUM}
do
    echo $i
done

prints

{1..4}
dogbane
  • 29,677
  • @dogbone: Thanks, I'm actually trying to find out how it is that the OP in the linked question can assert that their bash expands {1..$NUM} into the sequence 1 2 3 ...NUM –  Feb 24 '11 at 17:08