0

I've got an array bucket1=('10' '22' 'bucket1')

As you can see, one of the elements is the name of the array bucket1

Now I'm creating a new array by copying bucket1:

array1=("${bucket1[@]}")

Now I'm changing one of the elements in array1:

array1[1]='30'

echo ${array1[@]} gives 10 30 bucket1

Now I want to feed that change back to the array bucket1, but without knowing that array1 was created from bucket1. Instead I want to use the third element of array1, namely bucket1.

Something like:

declare -a ${array1[2]}=${array1[@]}

So that I end up with new bucket1 array, containing ('10' '30' 'bucket1')

In short: I want to copy an array, alter the copied array, apply the changes from the copied array in the original array using one of the elements from the copied array as the name of the original array.

It this possible?

4 Answers 4

3
bucket1=(10 20 bucket1)
tmp=("${bucket1[@]}")
tmp[1]=30
declare -a "${tmp[2]}"=("${tmp[@]}")
bash: syntax error near unexpected token `('

Hmm that doesn't work. Try one-by-one

for i in ${!tmp[@]}; do declare "${tmp[2]}[$i]"="${tmp[i]}"; done
echo ${bucket1[1]}
30

This is MUCH easier in ksh93

$ bucket1=(10 20 bucket1)
$ nameref tmp=bucket1
$ tmp[1]=30
$ echo ${bucket1[1]}
30
Sign up to request clarification or add additional context in comments.

2 Comments

+1 For future reference, the ksh93 solution will work in bash 4.3, replacing nameref with declare -n.
I had to upgrade Ubuntu to 14.04 to get Bash 4.3. Then I used the ksh93 solution, with the help from chepner. It works exactly how I want it to. Cheers!
0

You can use read -ra instead of declare here:

$> bucket1=('10' '22' 'bucket1')
$> array1=("${bucket1[@]}")
$> array1[1]='30 50'
$> declare -p array1
declare -a array1='([0]="10" [1]="30 50" [2]="bucket1")'

$> IFS=$'^G' && read -ra "${array1[2]}" < <(printf "%s^G" "${array1[@]}")
$> declare -p "${array1[2]}"
declare -a bucket1='([0]="10" [1]="30 50" [2]="bucket1")'
$> declare -p bucket1
declare -a bucket1='([0]="10" [1]="30 50" [2]="bucket1")'

All these declare -p have been used to print the array contents and can be removed in real script.

^G is typed using ControlVG together.

6 Comments

Reading from a here string will split space-containing elements of the array into separate elements in the new array. To see, change the first element of bucket1 to something like '10 4'.
I know that very well and provided this solution as proof of concept only since OP's input doesn't have spaces in array elements.
@chepner: Check updated answer now for making it safe for string with white spaces.
Well, as long as there is a character known to be absent from any element of the array, this will work, but this will not work in general.
Probability of a control character e.g. ^G in input! How realistic do you think that can be :)
|
0

With a little work, you can get the value of the array in a form suitable for use in the argument to declare.

IFS="=" read _ value <<< "$(set | grep '^array1=')"
declare -a "${array1[2]}=$value"

The quotes around the command substitution are necessary to work around a bug that is fixed in bash 4.3. However, if you have that version of bash, you can use named references to simplify this:

declare -n tmp=${array1[2]}
tmp=("${array1[@]}")

Comments

-1

Try this:

unset ${array1[2]}
declare -a ${array1[2]}="`echo ${array1[@]}`"

First we clear the array and then the output of echo will be stored in the new array name.

1 Comment

This sets the first element of the new array to the entire contents of the original array.

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.