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



Monday, 19 December 2016

Bash Scripting - Arrays with Examples

Arrays in Bash Scripting - In the last article about Shell Scripting, we learned about variables and their types - Normal variables, Shell variables and Environment variables. These variables are known as 'Scalar Variables', as they can hold only a single value. Bash comes with another type of variables, those have ability to hold multiple values, either of a same type or different types, known as 'Array'. Rather than creating a separate variable for each value to be stored, Array variable allows the programmer to use only one variable to hold 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. In this article, we will learn how arrays can be defined, how they can be used and some basic operations which we can perform on them.

bash-scripting-arrays

Initializing the Arrays

As we've seen in our article on variables, to declare a variable, we need a name, a value and the assignment (=') operator to assign that value to the variable.

Syntax:

varName=Value

Example:

myName="Mandar"
myAge=27

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 must say), you will be aware of initializing arrays, which looks more like follows:

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"

This certainly is not the way one would prefer to use. We can create an array by puting its elements within parenthesis and assigning it to a variable as shown below:

Syntax:

arrayName=(Value1 Value2 Value3 ... ValueN)

Example:

Fruits=(Apple Mango Orange Banana)

Another way is to use declare construct as below. This is similar to the above case, but uses declare construct.

Syntax:

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

Example:

declare -a Fruits=(Apple Mango Orange Banana)


Indexing

Each element in the array is associated with a positional parameter, called Index, using which it can easily be accessed. The first element of the array has the index '0', while the last element of the array containing 'n' elements, has the index 'n-1'. The array elements can be read from the array using their indices as shown below:

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 path name expansion.

Printing Array

In above section, we saw how an individual element can be extracted from an array. But, we haven't seen how all the elements can be displayed on the terminal screen. We use * and @ as follows:

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

Length of Array and Size of Array Elements

When using arrays, one must know how many elements are present in the array. No, you need not count them all. Instead, bash provides a special operator who does all the work for us. 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 size 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[@]}

# Size 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

Slicing arrays

With Slicing, we can extract a portion from an array (sub-array). For this, we need to provide START index, from where slice should begin, and Number, indicating how many elements should be fetched. Lets take a look at an example.

#!/bin/bash

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

In above example, slicing will begin from the element at index 2. It will fetch 3 elements from the array, meaning that next two elements (index 3 and index 4) will be fetched from the Fruits array.

Result:

Orange Banana Grapes

Similarly, we can slice characters from an array element, as shown below:

#!/bin/bash

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

In above example, we intend to work on element at index 4 in Fruits array and extract 3 characters starting from the one at index 2. Here, the element is Grapes and slice will get us ape.

Result:

ape

Search an Element and Get it replaced

One can also search for an element in already declared array and replace it by a different value. The syntax for this is -

Syntax:

${ArrayName[@]/Search/Replacement}

Example:

#!/bin/bash

Fruits=(Apple Mango Orange Banana Grapes Watermelon);
echo ${Fruits[@]/Grapes/Strawberry}

In above example, we search for the element Grapes in the array Fruits, replace it with Strawberry and print the updated Fruits array.

Result:

Apple Mango Orange Banana Strawberry Watermelon

Copy of an Array

As we know, we can access the entire array using ${ArrayName[@]}. When we put it within parenthesis, we get a copy of the same array, which can be saved in another variable.

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

Concatenation of Arrays

Another important operation we can perform on arrays is Concatenation. With this, we can add an array with another array, to get a combined version of the arrays. For this, we can put two arrays, side-by-side, within the parenthesis.

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 Elements to the Array

Now, we have two new fruits - Blackberry and Blueberry, to be added to the Fruits basket. We can add them to the array Fruits in somewhat similar manner, we saw earlier. Just access all the array elements as ${ArrayName[@]} and elements to be added, and include them all within parenthesis.

#!/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

So, we have reached the end of this article. Please share your views and feedback in the comment section below and stay tuned. Thank you.

0 comments:

Post a Comment