Here's a special case solution which is suitable when the appended (or prepended) string is a single character, and you don't need the values in a new array:
array=( aa bb cc )
IFS="]" # or, IFS="["
echo "${array[*]/#/ [}$IFS" # or, echo "$IFS${array[*]/%/] }
which produces output [aa] [bb] [cc]
.
- quoted form
"${array[*]}"
adds separator ]
between each pair (the first character of IFS
, this is where the constraints arise)
${array[*]/#/ [}
prepends
[
to each element (or /%/
form to append)
- finally add a trailing
]
(from IFS
) to the expanded value
If these steps are applied one by one you would get:
aa]bb]cc
[aa] [bb] [cc
[aa] [bb] [cc]
(You could also trivially recover the data as a new array if the values contain no whitespace.)
You can do the distinct prefix/postfix operations in a one-liner:
for ii in "${array[@]/#/foo }"; do echo "${ii/%/ bar}"; done
This is a more robust printf
solution that copies to a new array:
mapfile -d '' newarray < <(printf "foo %s bar\0" "${array[@]}")
albeit at the expense of a subshell (bash-4.4 required for mapfile -d
)
Finally a loop variation that copies to a new array, and also handles sparse and associative arrays, if needed.
declare -a array newarray # -a for indexed array, -A for associative
array=( one two three )
for ii in "${!array[@]}"; do
printf -v "newarray[$ii]" "foo %s bar" "${array[$ii]}"
done
(printf
is not required, you could assign directly, but it's clearer IMHO. bash
doesn't (yet!) support printing into an array, but zsh
does, giving you a loop free copy and transform one-liner, see Stéphane's answer above.)
What would be useful here is if bash
supported the common &
(like $MATCH
in zsh
) as a place-holder for the matched string in expansions. The code is there (and has been for a long time), but sadly it's not yet enabled (see shouldexp_replacement()
in subst.c
). If you enable it (two #if 0
changes, and recompile), this works as hoped:
array=( aa bb cc )
newarray=( "${array[@]/*/foo & bar}" )
No matter, perhaps available in the next version...
compgen
has a prefix/suffix operation (and supports &
, but not in a way we can use here). The best we can do with it isn't as good a muru's printf
solution:
compgen -P "foo " -S " bar" -W "${array[*]}"
(note -W
takes only a single option, so the array is flattened, and this causes problems with values with spaces or anything in IFS
)