66
array=(a b c d)

I would like to add a character before each element of the array in order to have this

array=(^a ^b ^c ^d)

An easy way to do that is to loop on array elements and change values one by one

for i in "${#array[@]}"
do
    array[i]="^"array[i]
done

But I would like to know if there is any way to do the same thing without looping on the array as I have to do the same instruction on all elements.

Thanks in advance.

2 Answers 2

102

Use Parameter Expansion:

array=("${array[@]/#/^}")

From the documentation:

${parameter/pattern/string}

Pattern substitution. The pattern is expanded to produce a pattern just as in pathname expansion. Parameter is expanded and the longest match of pattern against its value is replaced with string. If pattern begins with /, all matches of pattern are replaced with string. Normally only the first match is replaced. If pattern begins with #, it must match at the beginning of the expanded value of parameter. If pattern begins with %, it must match at the end of the expanded value of parameter. If string is null, matches of pattern are deleted and the / following pattern may be omitted. If parameter is @ or *, the substitution operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable subscripted with @ or *, the substitution operation is applied to each member of the array in turn, and the expansion is the resultant list.

Sign up to request clarification or add additional context in comments.

9 Comments

I have just another question. I would like to know if I can use this to change just a subset of an array because I obtain a syntax error when I run this array[@]:i:10=(${array[@]:i:10}/#/^})
@tuxworker I think you need to assign your sub-range array to another array variable first, then add the prefixes.
NB: If you have IFS=$'\n' (to handle names with whitespace) then the command will not keep the original array structure. It will just make array contain only 1 item (a string list), with all the changed strings. As seen if you run: declare -p array afterwards.
DIRS=("${DIRS[@]/%/\/module}") use % instead of # to substitute at the end. tldp.org/LDP/abs/html/string-manipulation.html
what if we want to add a number to all elements in an array?
|
10

This way also honor whitespaces in array values:

array=( "${array[@]/#/^}" )

Note, this will FAIL if array was empty and you set previously

set -u

I don't know how to eliminate this issue using short code...

3 Comments

Maybe array=("${array[@]:+${array[@]/#/^}}"), but I can't reproduce it (empty array + set -u) with neither bash-4.4.0, nor bash-4.1.5. In the latter you need this construct for iterating over an array with for, though.
How would you mark start and end of the string? From this: declare -a arr=(12 123); echo "${arr[@]/12/00}" I want 00 123 but I'm getting 00 003.
DIRS=("${DIRS[@]/%/\/module}") use % instead of # to substitute at the end. tldp.org/LDP/abs/html/string-manipulation.html

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.