Arrays

An array is a variable containing multiple values.

 

There is no maximum limit to the size of an array, nor any requirement that member variables be indexed or assigned contiguously.

 

Indexed arrays are zero-based with the first element starting from the number 0.

 

 

Creating Arrays

 

The easiest way to create a simple array with data is by using the =() syntax, separating elements with whitespace:

  • bikes=(Ducati Aprilia Triumph Yamaha Honda)

 

Elements containing whitespace should be encapsulated within quotes:

  • names=("Freddie Mercury" Bono 'Brian May' $bandmember)

 

Elements may also be indexed (remember starting from 0), with spaces if required:

  • cars=([0]=Probe [1]Saab [2]Lotus [16]BMW [17]DeLorean)

An array with holes in it is called a sparse array and can be quite useful.

 

Similarly, specific elements of an indexed array can be defined using their index value:

  • bikes[0]=Ducati
  • bikes[3]=Aprilia
  • bikes[4]=Triumph

 

Or, as an associative array:

  • declare -A transport=([bike]=Ducati [car]=probe [jet]=F35)

*note: capital A to signify an associative array. Also, if already declared as an indexed array, you will not be able to convert indexed to associative array and will therefore have to unset it first.

 

Globs can also be used to fill an array with filenames:

  • scripts=(~/"My Scripts"/*.sh)

Or adding to an array:

files+=(*.txt)

 

 

readarray

 

The readarray command is used to populate (read lines into) an array.

 

#!/bin/bash

readarray myvar < list.txt

for item in "${myvar[@]}"; do
	echo $item
done

*readarray is a synonym for mapfile

 

 

Reading Arrays

 

@ or * are used to refer to all elements of an array.

 

To get the number of elements:

  • echo "${#myvar[@]}"

 

A single element:

  • echo "${myvar[7]}"

 

All elements (at once):

  • echo "${myvar[@]}"

 

Iterate through all elements:

  • for value in "${myvar[*]}"; do echo "$value"; done

 

 

Deleting Arrays / Elements

 

Use unset on the array:

  • unset $myvar

 

Use unset on a specific array element:

  • unset ${myvar[2]}

 

 

A real world example

 

I had two sets of IP addresses that I wanted to check against each other.

 

The first set of about 60 IPs are from uptimerobot, are those that I want to whitelist.

 

However, I thought fail2ban had already caught some of the above IPs and added rules to iptables (which had ~2000 rules!), so I needed to check one list against the other.

 

I therefore created the following shell script... First, I assigned my uptimerobot IPs (in an external file) to a variable $myvar and then used readarray to assign the contents into an array: $MYIPs. I then used readarray again to assign all the IPs in the external banned.txt file into another array: $ADDRESSES.

 

The astute reader might say why not use the second method for both (ways of getting the external data into an array), but I wanted to do it this way to show the different ways to achieve the desired result.

 

Next, I iterated through each of the arrays, echo'ing out the IP from uptimerobot.txt when it matched against an IP from banned.txt

 

#!/bin/bash

myvar=uptimerobot.txt

readarray MYIPs < $myvar

readarray ADDRESSES < banned.txt

for item1 in "${MYIPs[@]}"; do
	for item2 in "${ADDRESSES[@]}"; do
		if [[ $item1 = $item2 ]]; then
			echo $item1
		fi
	done
done

 

Next, 'All' I had to do was delete the specific IP from the iptables rule chain and all was good.

 

 

Ref: https://www.thegeekstuff.com/2010/06/bash-array-tutorial