71

I have noticed there are two alternative ways of building loops in zsh:

  1. for x (1 2 3); do echo $x; done
  2. for x in 1 2 3; do echo $x; done

They both print:

1
2
3

My question is, why the two syntaxes? Is $x iterating through a different type of object in each of them?

Does bash make a similar distinction?

Addendum:

Why does the following work?:

#!/bin/zsh
a=1
b=2
c=5    

d=(a b c)    
for x in $d; do print $x;done

but this one doesn't?:

#!/bin/zsh
a=1
b=2
c=5

d=(a b c)    
# It complains with "parse error near `$d'"
for x $d; do print $x;done 
  • 5
    for the example that "doesn't work", which is a csh style for loop, you're missing the parentheses. for x ($d); do print $x; done will work, and it will match the first syntax that you have enumerated at the beginning of your question. – Tim Kennedy Oct 25 '11 at 4:22
  • 1
    It is SO crazy - that those two statements - indeed do not both "work the same". I literally can't get my head around it! I need to smoke some of what those shell designers were smoking', back in the day, lol. – alex gray Apr 14 '14 at 3:34
  • Careful, there is more to this story than initially appears. I invite you to check my answer. – jasonleonhard Feb 7 '17 at 3:48
  • 1
    I didn't see anyone else mention it, but both forms allow omission of do/done: for i ({0..4..2}) for j ({a..c}) echo "($i,$j)" = {0,2,4}x{a,b,c}. Semicolons apply to the outermost loop and redirections apply to the innermost, and if you need to change that, you only need braces: for i ({0..4..2}) { for j ({a..c}) echo "($i,$j)" } | cat -n = {1,...,9}*({0,2,4}x{a,b,c}). Of course you can combine loops with zsh expansion: for i ("("{0..4..2}","{a..c}")") echo $i – John P Jun 8 '18 at 4:45
74

Several forms of complex commands such as loops have alternate forms in zsh. These forms are mostly inspired by the C shell, which was fairly common when zsh was young but has now disappeared. These alternate forms act exactly like the normal forms, they're just a different syntax. They're slightly shorter, but less clear.

The standard form for the for command is for x in 1 2 3; do echo $x; done, and the standard form for the while command is while test …; do somecommand; done. Ksh, bash and zsh have an alternate form of for: for ((i = 0; i < 42; i++)); do somecommand; done, which mimics the for loops of languages like Pascal or C, to enumerate integers. Other exotic forms that exist in zsh are specific to zsh (but often inspired by csh).

| improve this answer | |
  • Thanks a lot @Guilles. I am still a bit confused though. Which form is the specific one to zsh? Also, I have added one example at the end of my OP where I can't figure out how to translate between syntaxes. If the difference is just syntax, how should I fix the second script in the addendum to make it work? – Amelio Vazquez-Reina Oct 24 '11 at 23:20
  • 3
    @intrpc See my updated answer. As for your last example, it doesn't work because you wrote for x $d and zsh expects either in or ( where you wrote $d. Punctuation marks and reserved words can't come from a variable expansion, they have to be parsed before the shell can start on the variable expansions. – Gilles 'SO- stop being evil' Oct 24 '11 at 23:33
  • @intrpc both are zsh specific. zsh was specifically designed to support both bourne, korn, and c-shell syntax, as it's a hybrid of all three. – Tim Kennedy Oct 25 '11 at 4:25
  • 1
    @pseyfert It works, but it doesn't have any advantage over the forms I show: it's less portable than the for (( … )) form and uses a lot of memory if 3 is large. – Gilles 'SO- stop being evil' Jan 15 '16 at 23:35
  • 2
    @alpha_989 In sh-like syntax, you need do after ));. Zsh also accepts another syntax for ((…)); COMMAND where COMMAND is a single command. That's why it accepts for ((i = 1; i<100; i++)); ghi show $i | grep "log". When it sees done after this, it complains because there was no do to end. See “Alternate Forms For Complex Commands” in the manual. – Gilles 'SO- stop being evil' Jun 9 '18 at 22:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.