Bash Arrays 3: Different Methods for Copying an Array

Pre-requistites

  1. Knowing how to declare an array and set its elements
  2. Knowing how to get the indices of an array
  3. Knowing how to cycle through an array

Setup

This is the same setup as the previous post
Let’s make a shell script. In your favourite editor type

#!/bin/bash

And save it somewhere as arrays.sh. Now we need to make it executable as follows:

[ahmed@amayem ~]$ chmod +x ./arrays.sh 
[ahmed@amayem ~]$ ./arrays.sh 
[ahmed@amayem ~]$ 

Looks good so far.
Let’s declare some arrays:

#Declarations
original=("zero" "1" "two" "3" "four")

Goal

Copy the array original into another variable such that it is an exact copy of the original.

Iteration 1: Is the array variable a pointer?

Let’s do the obvious thing and see if we can just say copy=$original

copy=$original
echo $copy ${copy[1]}

If $original is a pointer then echo ${copy[1]} should give me 1. This is the output:

[ahmed@amayem ~]$ ./arrays.sh 
zero 

${copy[1]} is not set, which means that $original is only the value of the element set at index 0. This was mentioned in the first post

Iteration 2: Copying array elements with ${original[*]}

original=("zero" "1" "two" "3" "four")
copy=${original[*]}
echo $copy ${copy[1]}

Gives us:

[ahmed@amayem ~]$ ./arrays.sh 
zero 1 two 3 four

At first sight this looks good because all the elements in the first array have been printed. However, ${copy[1]} has not been printed. That means that the element at ${copy[0]} is zero 1 two 3 four, which is not what we want, obviously.

Trying ${original[@]}

copy=${original[@]}

Has the same problem

Iteration 3: Using proper array assignemnt syntax

Notice that original is seen as an array because the right hand side of the assignment is a string inside brackets. The problem in the previous iteration is that there is nothing to indicate that copy is supposed to be an array. Let’s remedy that by adding brackets to the right hand side:

copy=(${original[*]})
echo $copy ${copy[1]}

This gives us the following:

[ahmed@amayem ~]$ ./arrays.sh 
zero 1

Which is exactly what we wanted. This also works with @ instead of *

Why “declare -a” by itself is not enough.

You many have tried this:

declare -a copy=${original[*]}
echo $copy ${copy[1]}

Gives us:

[ahmed@amayem ~]$ ./arrays.sh 
zero 1 two 3 four

Which is the same problems as before. That is because, though copy has been declared as an array, the assignment is in the form such that it is only assigned to the first element. The only way to assign more than one element to more than one index is to use the bracket notation mentioned above.

Breaking Iteration 3: Sparse arrays

Not every array must have serial indices that start from zero. Sometimes the array may be sparse, which means the indices are spread out. Let’s make our original array sparse by adding an element at the tenth index and see how our previous method works:

original[10]=10
copy=(${original[*]})
echo ${copy[*]} , ${original[10]} , ${copy[10]}

Gives us this:

[ahmed@amayem ~]$ ./arrays.sh 
zero 1 two 3 four 10 , 10 ,

So it seems that copy has all the same elements but not at the same index, since original has 10 at index 10 but copy has nothing.

Iteration 4: Copying sparse arrays with indices

To accomplish this we need to know both the elements and their indices. Unfortunately this will require more than one line. It will need a loop:

original=("zero" "1" "two" "3" "four")
original[10]=10

originalindices=${!original[*]}
for index in $originalindices;
do
    copy[$index]=${original[$index]}
done

echo ${copy[*]} , ${original[10]} , ${copy[10]}

Gives us the following:

[ahmed@amayem ~]$ ./arrays.sh 
zero 1 two 3 four 10 , 10 , 10

All the elements have been copied and the 10th element is also the same as the original. Mission accomplished.

References

  1. Bash man pages

Ahmed Amayem has written 90 articles

A Web Application Developer Entrepreneur.

  • vivek

    Thanks for the article. It really helped me a lot.

    • http://ahmed.amayem.com ahmedamayem

      My pleasure. Happy it helped.