Re: nested loops: '; done ; done' vs. '; done done'

On Jun 2, 1:36 am, Frank Terbeck <f...@xxxxxxxxxxxxxxxxxxx> wrote:

When nesting two for-loops, why does the following work?

for i in a b c ; do for e in x y z ; do echo $i$e ; done done

This is analogous to closing nested if's with fi fi fi ...

These keywords terminate the command, making it lexically clear that
the following material is the start of another command without the
need for a separating semicolon.

I was sure it had to be '; done ; done' at the end (which, of course,
works as well). But I tried the former in various shells (old-bourne,
ash, ksh93, zsh, bash...) and it always works. :-)

It's perfectly clear in the grammar given in the Single Unix

The specific phrase rule which generates your above for_clause is:

for name linebreak in wordlist sequential_sep do_group

Thus the nested for is generated by the do_group, which is:

do compound_list done

The compound_list isn't required to generate a terminating semicolon.
A simple loop terminated by done counts, grammatically, as a compound
list. The precise derivation chain is:

-> and_or
-> pipeline
-> pipe_sequence
-> command
-> compound_command
-> for_clause

And so you have ``do for_clause done'', which generates the done done.

That's a wrap! :)