15

Am trying to print a bunch of strings in a script (in zsh) and it doesn't seem to work. The code would work if I place the array in a variable and use it instead. Any ideas why this doesn't work otherwise?

for string in (some random strings to print) ; echo $string

3 Answers 3

32

The default form of the for command in zsh does not use parentheses (if there are any they are not interpreted as part of the for statement):

for string in some random strings to show
do
    echo _$string
done

This results in the following output:

_some
_random
_strings
_to
_show

So, echo _$string was run for each word after in. The list ends with the newline.

It is possible to write the whole statement in a single line:

for string in some random strings to show; do echo _$string; done

As usual when putting multiple shell commands in the same line, newlines just need to be replaced by ;. The exception here is the newline after do; while zsh allows a ; to be placed after do, it is usually not done, and in bash it would be a syntax error.

There are also several short forms available for for, all of which are equivalent to the default form above and produce the same output:

  • for single commands (to be exact: single pipelines or multiple pipelines linked with && or ||, where a pipeline can also be just a single command), there are two options:

    • the default form, just without do or done:

       for string in some random strings to show ; echo _$string
      
    • without in but with parentheses, also without do or done

       for string (some random strings to show) ; echo _$string
      
  • for a list of commands (like in the default form), foreach instead of for, no in, with parentheses and terminated by end:

    foreach string (some random strings to show) echo _$string ; end
    

In your case, you mixed the two short forms for single commands. Due to the presence of in, zsh did not take the parentheses as a syntactic element of the for command. Instead they are interpreted as a glob qualifier. Aside from the fact that you did not intend any filename expansions, this fails for two reasons:

  • there is no pattern (with or without actual globs) before the glob qualifier. So any matching filename would have to exactly match an empty string, which is just not possible

  • but mainly "some random strings to print" is not a valid glob qualifier. You probably get an error like "zsh: unknown file attribute: i" (at least with zsh 5.0.5, it may depend on the zsh version).

Sign up to request clarification or add additional context in comments.

1 Comment

Great answer! But I think it could be much improved with some example outputs, even if they seem trivial
13

Check the zsh forloop documentation:

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

3 Comments

I know that we can use variable to do this; I am asking if there is a way to avoid using it?
What is wrong with for x (1 2 3); do echo $x; done and for x in 1 2 3; do echo $x; done ?
Wow! Thats exactly right! No need for in when using array in place? Can you please update the answer, I will mark as answer.
4

You are probably trying to do this:

for string in some random strings to print ;do
   echo $string
done

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.