I want to pre- and postfix an array in bash similar to brace expansion.
Say I have a bash array
ARRAY=( one two three )
I want to b
Your last loop could be done in a whitespace-friendly way with:
EXPANDED=()
for E in "${ARRAY[@]}"; do
EXPANDED+=("prefix_${E}_suffix")
done
echo "${EXPANDED[@]}"
For arrays:
ARRAY=( one two three )
(IFS=,; eval echo prefix_\{"${ARRAY[*]}"\}_suffix)
For strings:
STRING="one two three"
eval echo prefix_\{${STRING// /,}\}_suffix
eval
causes its arguments to be evaluated twice, in both cases first evaluation results in
echo prefix_{one,two,three}_suffix
and second executes it. For array case subshell is used to avoid overwiting IFS
You can also do this in zsh:
echo ${${ARRAY[@]/#/prefix_}/%/_suffix}
Bash brace expansion don't use regexes. The pattern used is just some shell glob, which you can find in bash manual 3.5.8.1 Pattern Matching.
Your two-step solution is cool, but it needs some quotes for whitespace safety:
ARR_PRE=("${ARRAY[@]/#/prefix_}")
echo "${ARR_PRE[@]/%/_suffix}"
You can also do it in some evil way:
eval "something $(printf 'pre_%q_suf ' "${ARRAY[@]}")"
I have exactly the same question, and I come up with the following solution using sed's word boundary match mechanism:
myarray=( one two three )
newarray=( $(echo ${myarray[*]}|sed "s/\(\b[^ ]\+\)/pre-\1-post/g") )
echo ${newarray[@]}
> pre-one-post pre-two-post pre-three-post
echo ${#newarray[@]}
> 3
Waiting for more elegant solutions...
Prettier but essentially the same as the loop solution:
$ ARRAY=(A B C)
$ mapfile -t -d $'\0' EXPANDED < <(printf "prefix_%s_postfix\0" "${ARRAY[@]}")
$ echo "${EXPANDED[@]}"
prefix_A_postfix prefix_B_postfix prefix_C_postfix
mapfile
reads rows into elements of an array. With -d $'\0'
it instead reads null-delimited strings and -t
omits the delimiter from the result. See help mapfile
.