Working with Arrays in Linux Shell Scripting – Part 8

[‘

n

We cannot imagine a programming language without the concept of arrays. It doesn’t matter how they are implemented among various languages. Instead arrays help us in consolidating data, similar or different, under one symbolic name.

n

Working With Arrays in Shell Scripting
Working With Arrays in Shell Scripting

n

Here as we are concerned about shell scripting, this article will help you in playing around with some shell scripts which make use of this concept of arrays.

n

Array Initialization and Usage

n

With newer versions of bash, it supports one-dimensional arrays. An array can be explicitly declared by the declare shell-builtin.

n

declare -a var  rn

n

But it is not necessary to declare array variables as above. We can insert individual elements to array directly as follows.

n

var[XX]=<value>rn

n

where ‘XX’ denotes the array index. To dereference array elements use the curly bracket syntax, i.e.

n

${var[XX]}rn

n

Note: Array indexing always start with 0.

n

Another convenient way of initializing an entire array is by using the pair of parenthesis as shown below.

n

var=( element1 element2 element3 . . . elementN )rn

n

There is yet another way of assigning values to arrays. This way of initialization is a sub-category of the previously explained method.

n

array=( [XX]=<value> [XX]=<value> . . . )rn

n

We can also read/assign values to array during the execution time using the read shell-builtin.

n

read -a arrayrn

n

Now upon executing the above statement inside a script, it waits for some input. We need to provide the array elements separated by space (and not carriage return). After entering the values press enter to terminate.

n

To traverse through the array elements we can also use for loop.

n

for i in “${array[@]}”rndornt#access each element as $i. . .rndone rn

n

The following script summarizes the contents of this particular section.

n

#!/bin/bash rnrnarray1[0]=one rnarray1[1]=1 rnecho ${array1[0]} rnecho ${array1[1]} rnrnarray2=( one two three ) rnecho ${array2[0]} rnecho ${array2[2]} rnrnarray3=( [9]=nine [11]=11 ) rnecho ${array3[9]} rnecho ${array3[11]} rnrnread -a array4 rnfor i in "${array4[@]}" rndo rntecho $i rndone rnrnexit 0rn

n

Various Operations on Arrays

n

Many of the standard string operations work on arrays . Look at the following sample script which implements some operations on arrays (including string operations).

n

#!/bin/bash rnrnarray=( apple bat cat dog elephant frog ) rnrn#print first element rnecho ${array[0]} rnecho ${array:0} rnrn#display all elements rnecho ${array[@]} rnecho ${array[@]:0} rnrn#display all elements except first one rnecho ${array[@]:1} rnrn#display elements in a range rnecho ${array[@]:1:4} rnrn#length of first element rnecho ${#array[0]} rnecho ${#array} rnrn#number of elements rnecho ${#array[*]} rnecho ${#array[@]} rnrn#replacing substring rnecho ${array[@]//a/A} rnrnexit 0rn

n

Following is the output produced on executing the above script.

n

apple rnapple rnapple bat cat dog elephant frog rnapple bat cat dog elephant frog rnbat cat dog elephant frog rnbat cat dog elephant rn5 rn5 rn6 rn6 rnApple bAt cAt dog elephAnt frogrn

n

I think there is no significance in explaining the above script in detail as it is self-explanatory. If necessary I will dedicate one part in this series exclusively on string manipulations.

n

Command Substitution with Arrays

n

Command substitution assigns the output of a command or multiple commands into another context. Here in this context of arrays we can insert the output of commands as individual elements of arrays. Syntax is as follows.

n

array=( $(command) )rn

n

By default the contents in the output of command separated by white spaces are plugged into array as individual elements. The following script list the contents of a directory, which are files with 755 permissions.

n

#!/bin/bash rnrnERR=27 rnEXT=0 rnrnif [ $# -ne 1 ]; then rntecho "Usage: $0 <path>" rntexit $ERR rnfi rnrnif [ ! -d $1 ]; then rntecho "Directory $1 doesn't exists" rntexit $ERR rnfi rnrntemp=( $(find $1 -maxdepth 1 -type f) ) rnrnfor i in "${temp[@]}" rndo rntperm=$(ls -l $i) rntif [ `expr ${perm:0:10} : "-rwxr-xr-x"` -eq 10 ]; then rnttecho ${i##*/} rntfi rndone rnrnexit $EXTrn

n

Simulating Two-dimensional Arrays

n

We can easily represent a 2-dimensional matrix using a 1-dimensional array. In row major order representation elements in each row of a matrix are progressively stored in array indexes in a sequential manner. For an mXn matrix, formula for the same can be written as.

n

matrix[i][j]=array[n*i+j]rn

n

Look at another sample script for adding 2 matrices and printing the resultant matrix.

n

#!/bin/bash rnrnread -p "Enter the matrix order [mxn] : " t rnm=${t:0:1} rnn=${t:2:1} rnrnecho "Enter the elements for first matrix" rnfor i in `seq 0 $(($m-1))` rndo rntfor j in `seq 0 $(($n-1))` rntdo rnttread x[$(($n*$i+$j))] rntdone rndone rnrnecho "Enter the elements for second matrix" rnfor i in `seq 0 $(($m-1))` rndo rntfor j in `seq 0 $(($n-1))` rntdo rnttread y[$(($n*$i+$j))] rnttz[$(($n*$i+$j))]=$((${x[$(($n*$i+$j))]}+${y[$(($n*$i+$j))]})) rntdone rndone rnrnecho "Matrix after addition is" rnfor i in `seq 0 $(($m-1))` rndo rntfor j in `seq 0 $(($n-1))` rntdo rnttecho -ne "${z[$(($n*$i+$j))]}\t" rntdone rntecho -e "\n" rndone rnrnexit 0 rn

n

Even though there are limitations for implementing arrays inside shell scripting, it becomes useful in a handful of situations, especially when we handle with command substitution. Looking from an administrative point of view, the concept of arrays paved the way for development of many background scripts in GNU/Linux systems.

n

‘]