Zsh – Parameter Expansion Techniques

variable substitutionzsh

I tried to display the content of the variable fpath in column form using parameter expansion, and I couldn't do it.

After some trying and web browsing I just found another solution; which does exactly what I want. It is:

print -C1 $fpath

But I still wonder how to do it the other way. The closest I got was:

echo ${fpath//' '/'\n'}

But I fail to identify the white space character, so the '\n' substitution never takes place. I tried to no avail:

echo ${fpath// /'\n'}
echo ${fpath//'\t'/'\n'}

I wonder, out of curiosity, what I am doing wrong.

Best Answer

fpath is an array. You should not try to demote it to a string and then replace characters in it with newlines.

With ksh-like array expansion syntax:

$ printf '%s\n' "${fpath[@]}"
/usr/local/share/zsh/site-functions
/usr/share/zsh/site-functions
/usr/share/zsh/5.7.1/functions

With zsh, you can also use "$fpath[@]" or "${(@)fpath}".

You can also do:

$ printf '%s\n' $fpath
/usr/local/share/zsh/site-functions
/usr/share/zsh/site-functions
/usr/share/zsh/5.7.1/functions

But note that it skips empty elements of the array (likely not a problem for $fpath).

zsh's print builtin can also print elements one per line with the -l option. Like in ksh where the print builtin comes from, you do need the -r option though to print arbitrary data raw, so:

print -rl -- $fpath

would be equivalent to the standard printf '%s\n'.

They differ from -C1 when $fpath is an empty list in which case print -rC1 -- $fpath outputs nothing while print -rl and printf '%s\n' output one empty line, so

print -rC1 -- "$array[@]"

is probably the closest to what you want to print elements of the array one per line which in bash/ksh you could write:

[ "${#array[@]}" -eq 0 ] || printf '%s\n' "${array[@]}"
Related Question