Append (alter) each array element via parameter expansion (i.e. without printf)

arraybrace-expansionstringvariable substitutionzsh

Let the script below exemplify my quandary..

#!/bin/zsh

STUFF=( moose-hoof ovary clydsedale )

echo ${MINE=$(printf "MY-%s " $STUFF)}
echo ${MINE_EXP=${STUFF/^/MY-}}

MY-moose-hoof MY-ovary MY-clydsedale

moose-hoof ovary clydsedale

What are the right expansion flags to allow string concatenation on each element of the array?

Best Answer

Use $^array.

It turns the array into a sort of brace expansion of the array. As in when a=(foo bar baz), $^a would be a bit like {foo,bar,baz}.

$ a=(foo bar baz)
$ echo prefix${^a}suffix
prefixfoosuffix prefixbarsuffix prefixbazsuffix

For multiplexing arrays:

$ a=(1 2 3) b=(a b c)
$ echo $^a$^b
1a 1b 1c 2a 2b 2c 3a 3b 3c

Naturally, if the prefix or suffix contain shell special characters (like ; that separates commands or space that separate words, or $"'&*[?~...), they must be quoted:

echo 'p r e f i x '$^a' s u f f i x'

same as for csh's (and bash, ksh, zsh's):

echo 'p r e f i x '{foo,bar,baz}' s u f f i x'

$^a itself must not be quoted, "foo${^a}bar" would expand as one word. One case where you would want $^array to be quoted, the same as for $array is when you want to preserve empty elements. Then, you need to quote the array expansion and use the (@) flag or the "${array[@]}" syntax (reminiscent of the Bourne shell's "$@"):

$ array=(x '')
$ printf '<%s>\n' $array         # empties removed
<x>
$ printf '<%s>\n' "$array"       # array elts joined with spaces
<x >
$ printf '<%s>\n' "${(@)array}"  # empties preserved
<x>
<>
$ printf '<%s>\n' "$array[@]"    # empties preserved
<x>
<>
$ printf '<%s>\n' $^array$^array # empty removed
<xx>
<x>
<x>
$ printf '<%s>\n' "$^array$^array" # concatenation of joined arrays
<x x >
$ printf '<%s>\n' "$^array[@]$^array[@]" # multiplexing with empties preserved
<xx>
<x>
<x>
<>
Related Question