A Guide to Using Bash Arrays: Examples

unixmen

The Bourne Again Shell is the default shell on virtually every Linux distribution. While it’s not as fleshed out as most programming languages, it is considered a programming language by many.

Software engineers are accustomed to using the Linux command line to navigate several aspects of development. Linux administrators rely on it fully to complete their tasks. 

However, Bash arrays tend to remain one of the more obscure features of the CLI. Besides, the questionable syntax results in many developers turning away from using the arrays. 

Bash arrays are primarily utilized to store data in an indexed manner. You can compare it to storing data in variables, with the difference being that Bash arrays allow you to call back the data using predictable indexed numbers. Furthermore, Bash arrays also allow you to create associations. 

Bash arrays are an often-overlooked aspect of Bash scripting, mastering which can enable you to customize administrative tasks, run several tasks simultaneously, and even automate tasks. They are an invaluable tool to any Linux power user since using the arrays is necessary when working with scripts that store a large volume of information.

This tutorial walks you through all the fundamental operations of Bash arrays.

How to Use Bash Arrays

Before getting into the nitty-gritty, you must distinguish between the two Bash array types: indexed and associative arrays. 

The main difference between the two is that indexed arrays have keys that are ordered integers, whereas, in associative arrays, the keys are represented by strings. 

Further, there are several ways to initialize indexed arrays, but there is only one provision to create associative arrays – using the declare command. Let’s begin by taking a look at this command.

Creating Indexed and Associative Arrays with the Declare Command

Here’s how you can use the declare command to explicitly make an array:

$ declare -a example_array


The declare command serves as a method to set variables and attributes in Bash. The command above uses the -a switch, which indicates to the machine to create an indexed array of name “example_array.”

You can use the same command to create an associative array, but instead of using the -a switch, you must use the uppercase switch “-A,” like so:

$ declare -A example_array


As mentioned earlier, this is the only method to create associative arrays in Bash.

Other Ways to Declare Indexed Arrays

There is a way to create indexed arrays “on the fly,” as you would in many other popular programming languages, by assigning some values, like so:

$ example_array=(data1 data2)


You don’t need to assign multiple values to the array, as illustrated in the above command. You may also insert one value at a time by mentioning the index in the command:

$ example_array[0]=data1

 

Bash Array Operations

You can perform a handful of useful operations on a Bash array after creating it, such as printing its values and keys or modifying the array by removing or appending data.

Printing an Array’s Values

Displaying an array’s values is as simple as using this shell expansion syntax:

$ echo ${example_array[@]}


Alternatively, you can run:

$ echo ${example_array[*]}


These syntaxes allow you to access every value of an array, and both the commands fetch the same results. However, the two commands will produce different results if the expansion is quoted. 

The first command using the “@” will output one word for every array item – you can verify this by running a for loop. Let’s assume we have an array with two elements, “data1” and “data2.”

$ example_array=(data1 data2)


Here are the results of running a for loop that iterates through the elements of the array:

$ for i in “${example_array[@]}”; do echo “$i”; done
data1
data2


In contrast, when a variable is quoted in the second command which uses the asterisk, it will output only a single result containing all of the array’s elements:

$ for i in “${example_array[*]}”; do echo “$i”; done
data1 data2

 

Printing an Array’s Keys

Bash arrays facilitate the retrieval and printing of keys in associative and indexed arrays. The syntaxes are nearly identical to the commands you can use to print an array’s values – the only difference being the use of the “!” operator:

$ example_array=(data1 data2 data3)
$ for index in “${!example_array[@]}”; do echo “$index”; done
0
1
2


You can also work this way with an associative array, like so:

$ declare -A example_array
$ example_array=([key1]=data1 [key2]=data2)
$ for key in “${!example_array[@]}”; do echo “$key”; done
key1
key2 

 

Displaying the Size of an Array

You can use the following expansion to display the size (number of elements) of an array:

$ example_array=(data1 data2 data3)
$ echo “There are ${#example_array[@]} elements in the array”
There are 3 elements in the array


The array has three elements, “data1,” “data2,” and “data3,” and the syntax above retrieves the array’s values for the # character before the array’s name. This way, the syntax prints the size of the array rather than its contents.

Appending Elements to Arrays

Adding individual elements to indexed and associative arrays is possible by specifying their index or associative keys, respectively. 

If you’re working with indexed arrays, you can append elements to them using the += operation, like so:

$ example_array=(data1 data2)
$ example_array+=(data3)

 

By printing the contents of the array, we can see that “data3” is added to it:

$ echo “${example_array[@]}”
data1 data2 data3

 

You can also append multiple elements using a single command:

$ example_array=(data1 data2)
$ example_array+=(data3 data4)
$ echo “${example_array[@]}”
data1 data2 data3 data4

 

If you’re working with an associative array, you must specify the associated keys to add elements:

$ declare -A example_array

# Adding one element
$ example_array[key1]=”data1″

# Adding multiple elements
$ example_array+=([key2]=data2 [key3]=data3)

 

Removing Elements from Arrays

Deleting elements from arrays requires you to know the index or key depending on the type of array in question. You can use the unset command to remove the elements, like so:

$ example_array=(data1 data2 data3)
$ unset example_array[1]
$ echo ${example_array[@]}
data1 data3


In the example above, we create an array with three elements, “data1,” “data2,” and “data3.” Next, we remove “data2” from the array using unset and referencing its index in the array. 

Indexed arrays start from index 0; therefore, it is clear that the index of “data2” is 1. Checking the indexes of the array after removing “data2” reveals that index 1 is now missing:

$ echo ${!my_array[@]}
0 2

 

The unset command also works on associative arrays:

$ declare -A example_array
$ example_array+=([key1]=data1 [key2]=data2)
$ unset my_array[key1]
$ echo ${my_array[@]}
data2


In this example, the value referenced by “key1” is deleted, which leaves only data2 in the array.

If you need to delete an entire array, the process does not get more complicated, but just the opposite. All you have to do is pass the array’s name to unset as a parameter. There is no need to indicate any keys or indexes.

$ unset example_array
$ echo ${!example_array[@]}


In this example, attempting to print the array’s contents after deleting it returns an empty result.

Examples of Bash Arrays

Finding practical examples of Bash arrays can be challenging. While there is no shortage of scripts, they typically do not do much on your machine and tend to be used to solve math problems of different kinds. 

For instance, you may find an example of a Bash array calculating mathematical series, but this is one of the more interesting examples. 

The reason behind this lack of examples is the complex structures of the arrays. Most of the practical uses of Bash arrays are likely implemented on your machine already – but on a lower level using C language. One nice example of this is the “history” command that comes built into Bash.

If you’re interested in how that command works, navigate the Bash source tree to find the “built-ins” directory and explore “fc.def.” It is processed when the built-in features are compiled.

Since not every Linux shell supports Bash arrays, the lack of compatibility also contributes to the lack of examples.

Here is an example of an ISP using Bash arrays to distribute Apache server config files to the web farm’s hosts:

#!/bin/bash

if [ $(whoami) != ‘root’ ]; then
        echo “Must be root to run $0”
        exit 1;
fi
if [ -z $1 ]; then
        echo “Usage: $0 </path/to/httpd.conf>”
        exit 1
fi

httpd_conf_new=$1
httpd_conf_path=”/usr/local/apache/conf”
login=htuser

farm_hosts=(web03 web04 web05 web06 web07)

for i in ${farm_hosts[@]}; do
        su $login -c “scp $httpd_conf_new ${i}:${httpd_conf_path}”
        su $login -c “ssh $i sudo /usr/local/apache/bin/apachectl graceful”

done
exit 0

 

Before the arrays come into the picture, the example script above checks if the right user is running the script and whether the correct arguments are in use. The host names that need to be configured appear in the farm_hosts array.

Next, all hosts are supplied with the Apache configuration file, and the script restarts the daemon. If you work with Bash scripts a lot, you may notice that the commands in the above example are from the Secure Shell suite and encrypt the connections to the remote hosts.

Let’s get into another example.

Let’s assume a company offers demos on their website, all of which need to be tested weekly. Doing this becomes easier with a cron job that fills an array with potential testers. The job can use date +%w to narrow down the weeks of the year and run the modulo operation to determine the index.

#!/bin/bash
# This get-tester-address.sh script finds a tester to check the demos on the website 
# for the week
#
# It begins by testing whether Bash supports arrays

whotest[0]=’test’ || (echo ‘FAIL: Current Bash version does not support arrays.’ && exit 2)                                                                              

#
# Next, the tester candidates are specified
#

wholist=(
     ‘Kirk Ira <kirk@example.com>’
     ‘Tennyson Read <tenny@example.com>’
     ‘Lavender Pen <lp@example.com>’
     ‘Wyatt Boyce <wyatt@example.com>’
     ‘Cindra Jonny <cindra@example.com>’
   )
#
# Now, we count the number of potential candidates
# by looping till an empty string is found
#
count=0
while [ “x${wholist[count]}” != “x” ]
do
   count=$(( $count + 1 ))
done                                                                                

#
# Finally, we work out who needs to pick up the task for the week
#
week=`date ‘+%W’`    # The week 
week=${week#0}       # Removing possible leading zero                                                                                

let “index = $week % $count”   # Finding the tester

email=${wholist[index]}     # Retrieving their email address     

echo $email     # Printing the email address

 

The company can integrate this script into another Bash script, which uses a “here” document to email the selected tester and notifies them of their duties. 

Conclusion

Bash scripts are an invaluable tool to automate tasks, and incorporating arrays allows you to store a lot of data.

While using the arrays is not challenging, the syntax is different from other programming languages you may be familiar with. With this guide handy, you can work with Bash arrays hassle-free.