Introduction to Linux - A Hands on Guide | Linux Bible | Linux From Scratch | A Newbie's Getting Started Guide to Linux | Linux Command Line Cheat Sheet | More Linux eBooks



Friday, 11 October 2013

Working with 'Arrays' in BASH Scripting

     We have been dealing with some simple Bash Scripts in our recent articles on Basic Linux Shell Scripting Language. The variables we used in those scripts are called as 'Scalar Variables' as they can hold only a single value. Linux shell provides an another kind of variable which stores multiple values, either of a same type or different types, known as 'Array Variable'. Rather than creating a separate variable for each value, Array variable lets the programer to use a single variable to store multiple values at the same time. There is no maximum limit for the Array Size and  no such compulsion to store the values in contiguous manner.


    This article explains  how arrays are defined in the Bash scripts, how they are used in the Bash scripts and some basic operations on them. Those who are new to Linux Shell Scripting are recommended to read our article - Getting Started - Basic Linux Shell Scripting Language.

Initializing the Arrays

Let us compare the Scalar variables and Array variables on the basis of their declaration.

    The method of initializing Scalar variables is pretty straight forward. You just need a variable, a value and a '=' operator to assign that value to the variable.

Syntax:

varName=Value
Example:

myName="Mandar"
myAge=24
    As quoted above, we can use a single Array variable to store multiple values. In the simplest method for storing a value in any Array variable we need name of the array and an index. If you are familiar with C Language (or any other programming language I should say), you will be aware of following Array initialization syntax.

Syntax:

arrayName[index]=Value
Note: First element of any array will be it index '0', i.e. arrayName[0] will be the first element of the arrayName.

Example:

Fruits[0]="Apple"
Fruits[1]="Mango"
Fruits[2]="Orange"
Fruits[3]="Banana"
Another ways with which you can initialize the Array variables are as follows:

Syntax:

arrayName=(Value1 Value2 Value3 .. ValueN)
Example:

Fruits=(Apple Mango Orange Banana)
Syntax:

declare -a arrayName=(Value1 Value2 Value3 .. ValueN)
Example:

declare -a Fruits=(Apple Mango Orange Banana)

Accessing Array Elements Using Indices

After initializing the arrays, you can access the array elements using their indices as follows:

Syntax:

${arrName[index]}
Example:

#1st Element in Array 'Fruits'
${Fruits[0]}

#2nd Element in Array 'Fruits'
${Fruits[1]}

#3rd Element in Array 'Fruits'
${Fruits[2]}

#4th Element in Array 'Fruits'
${Fruits[3]}
Note: The braces are required to avoid conflicts with pathname expansion.

Displaying the Entire Array

You can access all the items at once using any one of the ways mentioned below:

Syntax:

${arrName[@]}

OR

${arrName[*]}
Example:

${Fruits[@]}

OR

${Fruits[*]}
Let us verify this by running the following script:

#!/bin/bash

Fruits=(Apple Mango Orange Banana)

echo "${Fruits[@]}"
Result:

Apple Mango Orange Banana

Displaying the Length of an Array and Array Elements

We can display the length of the whole array or any array element by using a special operator '#'. Here, length of an array will be displayed in terms of number of elements present in it whereas length of an array element will be in terms of number of characters in that element.

Syntax:

#Length of arrayName = No. of elements present in arrayName

${#ArrayName[@]}

#Length of arrayName[index] = No. of characters in arrayName[index]

${#arrayName[index]}
Example:

#Length of Fruits = No. of elements present in "Fruits"

${#Fruits[@]}

#Length of Fruits[1] = No. of characters in "Mango"

${#Fruits[1]}
Let's verify this by writing a script:

#!/bin/bash

Fruits=(Apple Mango Orange Banana)

echo "Length of 'Fruits' = ${#Fruits[@]}"
echo "Length of 'Fruits[1]' = ${#Fruits[1]}"
Result:

Length of 'Fruits' = 4
Length of 'Fruits[1]' = 5

Displaying the Array Elements Using Offset and Length

Just have a look on the following script:

#!/bin/bash

Fruits=(Apple Mango Orange Banana Grapes Watermelon);
echo ${Fruits[@]:2:3}
The above script will fetch 3 elements from the one at index 2 located in 'Fruits' array.

Result:

Orange Banana Grapes
    Let us now create a similar kind of script which will display 3 characters of an array element present at index 4 in the array starting from the character at index 2.

#!/bin/bash

Fruits=(Apple Mango Orange Banana Grapes Watermelon);
echo ${Fruits[4]:2:3}
Result:

ape

Searching and Replacing Array Elements

Observe the following script:

#!/bin/bash

Fruits=(Apple Mango Orange Banana Grapes Watermelon);
echo ${Fruits[@]/Grapes/Strawberry}
   This script will search for 'Grapes' in the array 'Fruits', replace it with 'Strawberry' and print the updated 'Fruits' array.

Result:

Apple Mango Orange Banana Strawberry Watermelon

Copying an Array

Syntax:

arrayName1=(Value1 Value2 Value3 .. ValueN)
arrayName2=("${arrayName1[@]}")
Example:

#!/bin/bash
Fruits=(Apple Mango Orange Banana)
myFavFruits=("${Fruits[@]}")
echo ${myFavFruits[@]}
Result:

Apple Mango Orange Banana

Concatenate Two Arrays

Syntax:

arrayName1=(value1 value2 value3 .. valueN)
arrayName2=(VALUE1 VALUE2 VALUE3 .. VALUEn)

newArray=("${arrayName1[@]}" "${arrayName2[@]}")
Example:

#!/bin/bash
Linux=(Ubuntu LinuxMint CentOS Fedora)
Windows=(WinXP Win7 Win8)

LinWin=("${Linux[@]}" "${Windows[@]}")
echo ${LinWin[@]}
Result:

Ubuntu LinuxMint CentOS Fedora WinXP Win7 Win8

Adding New Elements to the Original Array

Now, we have two new fruits - Blackberry and Blueberry, to be added to the 'Fruits' basket. Following script will add these two fruits to the existing array of 'Fruits'.

#!/bin/bash

Fruits=(Apple Mango Orange Banana Grapes Watermelon);

Fruits=(${Fruits[@]} Blackberry Blueberry)

echo "${Fruits[@]}"
Result:

Apple Mango Orange Banana Grapes Watermelon Blackberry Blueberry

Removing an Element From an Array

To remove an element completely from an array completely, we need to merge two sub-arrays: First sub-array will consist of all those elements present before the element to be removed and Second sub-array will contain all those elements arriving after the element to be removed. Let us consider that, we have to remove 'Banana' present at index 3 in 'Fruits' array.

#!/bin/bash

Fruits=(Apple Mango Orange Banana Grapes Watermelon Blackberry Blueberry)

idx=3

Fruits=(${Fruits[@]:0:$idx} ${Fruits[@]:$(expr $idx + 1)})

echo "${Fruits[@]}"
    In above script, ${Fruits[@]:0:$idx} fetches 3 elements starting from index 0, i.e. Fruits[0], Fruits[1] and Fruits[2], and ${Fruits[@]:$(expr $idx + 1)} extracts all the elements from index 4 to the last index. These two sub-arrays are merged to create a new 'Fruits' array which does not contain 'Banana'

Result:

Apple Mango Orange Grapes Watermelon Blackberry Blueberry
    Another alternative to remove an element from an array is to assign a 'null' value to the element. You can assign a null value to an element using 'unset' as follows:

#!/bin/bash

Fruits=(Apple Mango Orange Banana Grapes Watermelon Blackberry Blueberry)

unset Fruits[3]

echo "${Fruits[@]}"
Result:

Apple Mango Orange Grapes Watermelon Blackberry Blueberry
   The difference in both these techniques to remove an element from an array will be observed when you add following line in the script:

echo "${Fruits[3]}"
   If you use first method to remove the element from the array, above line will show you 'Grapes' in the result. If you use 'unset', then it will display null value which was assigned to the concerned element.

You can also remove an array element using patterns as shown in following script:

#!/bin/bash

Fruits=(Apple Mango Orange Banana Grapes Watermelon Blackberry Blueberry)

Fruits2=(${Fruits[@]/Ban*/})

echo "${Fruits2[@]}"
To delete an entire array, you can use 'unset' in the script as follows:

unset arrayName

That's all about Arrays..!


1 comment:

  1. Instead of Searching and Replacing Array Elements, I just want to search if element exists or not.

    ReplyDelete