Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A bash loop with braces?

I stumbled across this oddity and can't quite figure out why it works:

$ for ((i=0;i<8;i++)) {
>   printf '%d...' "$i";
> }; echo
0...1...2...3...4...5...6...7...

A for loop in bash using brace syntax? I can't reproduce this using a non-arithmetic for loop at all, and the manpage and help both seem to require the do:

$ help for
<SNIP>
for ((: for (( exp1; exp2; exp3 )); do COMMANDS; done
    Arithmetic for loop.

    Equivalent to
        (( EXP1 ))
        while (( EXP2 )); do
            COMMANDS
            (( EXP3 ))
        done

Hmm, so if I just…

$ ((i=0)); while ((i<8)) { printf '%d...' "$i"; ((i++)); }
-bash: syntax error near unexpected token `{'

Nope!

Is this braced for-loop syntax

  1. Documented anywhere (official?)
  2. A legitimate different way to represent an arithmetic for loop in Bash?
  3. Just something I'm missing about how a "normal" arithmetic for loop is interpreting the input?

P.S. – This was tested on OS X Mavericks with both a homebrew-installed Bash 4.2.45(2)-release as well as the vanilla 3.2.51(1)-release.

like image 406
kojiro Avatar asked Mar 24 '14 20:03

kojiro


1 Answers

Transferring some comments into an answer:

AFAIK, it is a largely undocumented hack in Bash, probably needed for compatibility with the Bourne shell which also supported the brace notation, also undocumented. It is not peculiar to Mac OS X; it works like that on Ubuntu 12.04 too. It doesn't seem to work with while loops or until loops in Bash, though.

How do you write an arithmetic for loop in Bourne shell syntax?

It is an optional way of writing the body of the for loop; the condition would be written differently in Bourne shell, but you could write things like

for i in 1 2 3
{
    echo $i
}

in Bourne shell, or use do in place of { and done in place of }.

(I'd forgotten that it existed until your question reminded me of it; I've never used it seriously because it was not documented and hence not guaranteed to be supported.)

The do ... done construct cannot be used where { ... } can be used; you can only use do ... done after a for, while or until loop, whereas you can write { echo Hi; } anywhere a command could appear (e.g. if { echo Hi; }; then echo Lo; fi. You can't do that with do and done.

The best way to check the veracity of this answer is likely to be to download the Heirloom Bourne Shell from the Heirloom Project.


I've downloaded the source code for the Heirloom Bourne Shell (a CVS repository) and built it, and tested it. It does indeed accept the braces after the for loop, and refuses to recognize them as surrogates for do and done after an until or while loop.

like image 68
Jonathan Leffler Avatar answered Nov 15 '22 20:11

Jonathan Leffler