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)

Tags:

Zsh

Array