Remove all empty strings from an array in Zsh
There is the parameter expansion ${name:#pattern}
(pattern can be empty), which will work on elements of an array:
a=('a' '' 'b' 'c')
echo ${(j./.)a:#}
# If the expansion is in double quotes, add the @ flag:
echo "${(@j./.)a:#}"
man 1 zshexpn
:
${name:#pattern}
If the pattern matches the value of name, then substitute the empty string; otherwise, just substitute the value of name. If name is an array the matching array elements are removed (use the(M)
flag to remove the non-matched elements).
Well, zsh has a :|
parameter expansion operator for array subtraction - so a klunky way to do it would be to define a second array consisting of only an empty element
b=('')
and then do
% echo ${(j./.)a:|b}
a/b/c
However it feels like there ought to be a way to do it without the additional array
... and indeed there is.
That's what zsh
does by default when you leave a parameter expansion unquoted¹.
So:
a=($a)
Will remove the empty elements in the $a
array.
¹ I generally consider that a misfeature. See the rc
/es
or fish
shells for better arrays that don't do that. That's probably there so as to provide some level of compatibility with the sparse arrays of ksh
/bash
. ksh
/bash
arrays not only do empty removal upon unquoted array expansion (written ${a[@]}
there), but also split+glob, which means you can't really use arrays unquoted there unless you disable globbing and set $IFS
to the empty string (IFS=; set -o noglob; a=(${a[@]})
then does empty removal only there like in zsh
in addition to making the array non-sparse)