Iterating on words and lines in zsh

When writing zsh scripts, I often needs to iterate on elements, but depending on how I create them, they can either be a core zsh array, a string of words, or the output of a command, delimited by newlines.

Iterating on an array

Iterating on arrays in zsh has a pretty straightforward syntax:

local projects=(firost aberlaas golgoth);
for project in $projects; do
   echo "${project} is one of my projects";
 done

Handling string of words

By default, zsh does not split a string in words like other shells (Bash) do, so iterating on words requires the ${=} syntax.

The ${=} notation triggers the Bash-compatible behavior by switching the SH_WORD_SPLIT zsh option for that variable.

Iterating on the words

local projects="firost aberlaas golgoth";
for project in ${=projects}; do
   echo "${project} is one of my projects";
 done

Accessing one element specifically

Note that if I want to convert the string of words into an array, to specifically access one of its elements, I need to wrap it in ().

local projects="firost aberlaas golgoth";
local projectsArray=(${=projects})
echo "$projectsArray[2] is my second project"

A note on words

Note that zsh will split by words, meaning that multiple spaces will be removed:

local projects="   firost        aberlaas            golgoth    ";
local projectsArray=(${=projects})
echo "$projectsArray[2] is still my second project"

Iterating on lines in a string

New lines are considered words separators, so technically the ${=} could be used to split a string by newlines. But this will also split by spaces, so if your lines contain spaces, you final array will not be what you expect.

To split only by new lines and not by space, you need to use the ${(f)} syntax. This proves useful when parsing long output from other commands

Iterating on the lines

local projects="$(ls)";
for project in ${(f)projects}; do
   echo "${project} is a project file in my dir";
done

Accessing one line specifically

local projects="$(ls)";
local projectsArray=(${(f)projects})
echo "$projectsArray[2] is my second project"

Tags : #zsh

Want to add something ? Feel free to get in touch on Twitter : @pixelastic