The Ultimate Bash Array Tutorial with 15 Examples

by Sasikala on June 3, 2010

An array is a variable containing multiple values may be of same type or of different type.  There is no maximum limit to the size of an array, nor any requirement that member variables be indexed or assigned contiguously. Array index starts with zero.

In this article, let us review 15 various array operations in bash.

This article is part of the on-going Bash Tutorial series. For those who are new to bash scripting, get a jump-start from the Bash Scripting Introduction tutorial.

1. Declaring an Array and Assigning values

In bash, array is created automatically when a variable is used in the format like,

name[index]=value
  • name is any name for an array
  • index could be any number or expression that must evaluate to a number greater than or equal to zero.You can declare an explicit array using declare -a arrayname.
$ cat arraymanip.sh
#! /bin/bash
Unix[0]='Debian'
Unix[1]='Red hat'
Unix[2]='Ubuntu'
Unix[3]='Suse'

echo ${Unix[1]}

$./arraymanip.sh
Red hat

To access an element from an array use curly brackets like ${name[index]}.

2. Initializing an array during declaration

Instead of initializing an each element of an array separately, you can declare and initialize an array by specifying the list of elements (separated by white space) with in a curly braces.

Syntax:
declare -a arrayname=(element1 element2 element3)

If the elements has the white space character, enclose it with in a quotes.

#! /bin/bash
$cat arraymanip.sh
declare -a Unix=('Debian' 'Red hat' 'Red hat' 'Suse' 'Fedora');

declare -a declares an array and all the elements in the parentheses are the elements of an array.

3. Print the Whole Bash Array

There are different ways to print the whole elements of the array. If the index number is @ or *, all members of an array are referenced. You can traverse through the array elements and print it, using looping statements in bash.

echo ${Unix[@]}

# Add the above echo statement into the arraymanip.sh
#./t.sh
Debian Red hat Ubuntu Suse

Referring to the content of a member variable of an array without providing an index number is the same as referring to the content of the first element, the one referenced with index number zero.

4. Length of the Bash Array

We can get the length of an array using the special parameter called $#.

${#arrayname[@]} gives you the length of the array.

$ cat arraymanip.sh
declare -a Unix=('Debian' 'Red hat' 'Suse' 'Fedora');
echo ${#Unix[@]} #Number of elements in the array
echo ${#Unix}  #Number of characters in the first element of the array.i.e Debian
$./arraymanip.sh
4
6

5. Length of the nth Element in an Array

${#arrayname[n]} should give the length of the nth element in an array.

$cat arraymanip.sh
#! /bin/bash

Unix[0]='Debian'
Unix[1]='Red hat'
Unix[2]='Ubuntu'
Unix[3]='Suse'

echo ${#Unix[3]} # length of the element located at index 3 i.e Suse

$./arraymanip.sh
4

6. Extraction by offset and length for an array

The following example shows the way to extract 2 elements starting from the position 3 from an array called Unix.

$cat arraymanip.sh
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
echo ${Unix[@]:3:2}

$./arraymanip.sh
Suse Fedora

The above example returns the elements in the 3rd index and fourth index. Index always starts with zero.

7. Extraction with offset and length, for a particular element of an array

To extract only first four elements from an array element . For example, Ubuntu which is located at the second index of an array, you can use offset and length for a particular element of an array.

$cat arraymanip.sh
#! /bin/bash

Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
echo ${Unix[2]:0:4}

./arraymanip.sh
Ubun

The above example extracts the first four characters from the 2nd indexed element of an array.

8. Search and Replace in an array elements

The following example, searches for Ubuntu in an array elements, and replace the same with the word ‘SCO Unix’.

$cat arraymanip.sh
#!/bin/bash
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');

echo ${Unix[@]/Ubuntu/SCO Unix}

$./arraymanip.sh
Debian Red hat SCO Unix Suse Fedora UTS OpenLinux

In this example, it replaces the element in the 2nd index ‘Ubuntu’ with ‘SCO Unix’. But this example will not permanently replace the array content.

9. Add an element to an existing Bash Array

The following example shows the way to add an element to the existing array.

$cat arraymanip.sh
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
Unix=("${Unix[@]}" "AIX" "HP-UX")
echo ${Unix[7]}

$./arraymanip.sh
AIX

In the array called Unix, the elements ‘AIX’ and ‘HP-UX’ are added in 7th and 8th index respectively.

10. Remove an Element from an Array

unset is used to remove an element from an array.unset will have the same effect as assigning null to an element.

$cat arraymanip.sh
#!/bin/bash
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');

unset Unix[3]
echo ${Unix[3]}

The above script will just print null which is the value available in the 3rd index. The following example shows one of the way to remove an element completely from an array.

$ cat arraymanip.sh
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
pos=3
Unix=(${Unix[@]:0:$pos} ${Unix[@]:$(($pos + 1))})
echo ${Unix[@]}

$./arraymanip.sh
Debian Red hat Ubuntu Fedora UTS OpenLinux

In this example, ${Unix[@]:0:$pos} will give you 3 elements starting from 0th index i.e 0,1,2 and ${Unix[@]:4} will give the elements from 4th index to the last index. And merge both the above output. This is one of the workaround to remove an element from an array.

11. Remove Bash Array Elements using Patterns

In the search condition you can give the patterns, and stores the remaining element to an another array as shown below.

$ cat arraymanip.sh
#!/bin/bash
declare -a Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora');
declare -a patter=( ${Unix[@]/Red*/} )
echo ${patter[@]}

$ ./arraymanip.sh
Debian Ubuntu Suse Fedora

The above example removes the elements which has the patter Red*.

12. Copying an Array

Expand the array elements and store that into a new array as shown below.

#!/bin/bash
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
Linux=("${Unix[@]}")
echo ${Linux[@]}

$ ./arraymanip.sh
Debian Red hat Ubuntu Fedora UTS OpenLinux

13. Concatenation of two Bash Arrays

Expand the elements of the two arrays and assign it to the new array.

$cat arraymanip.sh
#!/bin/bash
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
Shell=('bash' 'csh' 'jsh' 'rsh' 'ksh' 'rc' 'tcsh');

UnixShell=("${Unix[@]}" "${Shell[@]}")
echo ${UnixShell[@]}
echo ${#UnixShell[@]}

$ ./arraymanip.sh
Debian Red hat Ubuntu Suse Fedora UTS OpenLinux bash csh jsh rsh ksh rc tcsh
14

It prints the array which has the elements of the both the array ‘Unix’ and ‘Shell’, and number of elements of the new array is 14.

14. Deleting an Entire Array

unset is used to delete an entire array.

$cat arraymanip.sh
#!/bin/bash
Unix=('Debian' 'Red hat' 'Ubuntu' 'Suse' 'Fedora' 'UTS' 'OpenLinux');
Shell=('bash' 'csh' 'jsh' 'rsh' 'ksh' 'rc' 'tcsh');

UnixShell=("${Unix[@]}" "${Shell[@]}")
unset UnixShell
echo ${#UnixShell[@]}

$ ./arraymanip.sh
0

After unset an array, its length would be zero as shown above.

15. Load Content of a File into an Array

You can load the content of the file line by line into an array.

#Example file
$ cat logfile
Welcome
to
thegeekstuff
Linux
Unix

$ cat loadcontent.sh
#!/bin/bash
filecontent=( `cat "logfile" `)

for t in "${filecontent[@]}"
do
echo $t
done
echo "Read file content!"

$ ./loadcontent.sh
Welcome
to
thegeekstuff
Linux
Unix
Read file content!

In the above example, each index of an array element has printed through for loop.

Recommended Reading

Bash 101 Hacks, by Ramesh Natarajan. I spend most of my time on Linux environment. So, naturally I’m a huge fan of Bash command line and shell scripting. 15 years back, when I was working on different flavors of *nix, I used to write lot of code on C shell and Korn shell. Later years, when I started working on Linux as system administrator, I pretty much automated every possible task using Bash shell scripting. Based on my Bash experience, I’ve written Bash 101 Hacks eBook that contains 101 practical examples on both Bash command line and shell scripting. If you’ve been thinking about mastering Bash, do yourself a favor and read this book, which will help you take control of your Bash command line and shell scripting.


Linux Sysadmin Course Linux provides several powerful administrative tools and utilities which will help you to manage your systems effectively. If you don’t know what these tools are and how to use them, you could be spending lot of time trying to perform even the basic administrative tasks. The focus of this course is to help you understand system administration tools, which will help you to become an effective Linux system administrator.
Get the Linux Sysadmin Course Now!

If you enjoyed this article, you might also like..

  1. 50 Linux Sysadmin Tutorials
  2. 50 Most Frequently Used Linux Commands (With Examples)
  3. Top 25 Best Linux Performance Monitoring and Debugging Tools
  4. Mommy, I found it! – 15 Practical Linux Find Command Examples
  5. Linux 101 Hacks 2nd Edition eBook Linux 101 Hacks Book

Bash 101 Hacks Book Sed and Awk 101 Hacks Book Nagios Core 3 Book Vim 101 Hacks Book

{ 40 comments… read them below or add one }

1 Tanmay Joshi June 3, 2010 at 5:59 am

Good article.

I am new to linux and following your articles very closely.
Just wanted to confirm if the below line as typo in displaying code or the sentence it self
“declare -a declares an array and all the elements in the curly brackets are the elements of an array” – are we using curly brackets or parantheses?

Thanks,
Tanmay

2 Gabriele June 3, 2010 at 6:47 am

Great stuff!!!
Regards

Gabriele

3 iambryan June 3, 2010 at 8:52 am

Great examples :)

There is a correction for number 6 though as the OpenLinux array entity is missing the closing single quote which would as you know, throw an error.

Keep up the good work

4 Ramesh Natarajan June 3, 2010 at 10:11 pm

@Tanmay, @Bryan,

Thanks for pointing out the issues. They are fixed now.

5 hari June 3, 2010 at 11:50 pm

best best

best

6 Chris F.A. Johnson June 4, 2010 at 8:01 am

1. “echo ${Unix[1]}” will not necessarily print element 1 from the array. For example:

$ Unix[1]=” AAA BBB CCC”
$ echo ${Unix[1]}
AAA BBB CCC

Leading and trailing whitespace will be lost, and consecutive whitespace will be reduced to a single space.

It should be:

echo “${Unix[1]}”

(Almost all the examples exhibit the same error because the variable reference is not quoted. Whether the error is manifest in the output depends on the contents of the array elements.)

2. “declare -a” is unnecessary

3. “echo ${Unix[@]}” has the same problem as #1

4. More accurately, ${#arrayname[@]} gives you the number of elements in the array.

9. Since bash3, elements can also be appended to an array with “+=”:

Unix+=( “AIX” “HP-UX” )

15. filecontent=( `cat “logfile” `)

More efficient, as it doesn’t require an external command, is:

filecontent=( `< "logfile" `)

(Note: this doesn't read the file line by line; it reads it word by word. Try it on a file with more than one word on a line.)

Since bash4, this can be done even more efficiently with the mapfile builtin:

mapfile -t filecontent < "$logfile"

for t in "${filecontent[@]}"

The loop is not necessary:

printf "%s\n" "${filecontent[@]}"

7 anonymous June 4, 2010 at 10:01 pm

Note that the example will not read the following file into an array (where each line is an element).
This is the first line
This is the second line
This is the final line
To read the file (as lines) into an array do:
{
IFS=$’\n’
array_name=( $(cat filename) )
}
Note the use of the “{” in this example allows the changing of IFS value without having to save it and restore it.

8 TheFu June 7, 2010 at 9:36 am

I love it! Great examples to display simple use cases.

Sadly, the syntax for arrays in Bash is too complex for me, so I’ll be staying with Perl. How often do you hear that? ;) I’ll probably be back here when perl isn’t allowed on a system for some reason.

9 sbaginov June 9, 2010 at 4:47 am

Simply awsome! Thank you!

10 WaS June 21, 2010 at 3:36 am

When you do:

filecontent=( `cat “logfile” `)

and logfile have one “*” you get a list of archives in your directory, how i can solve it?

Thx

11 Chris F.A. Johnson June 21, 2010 at 11:34 am

WaS, when you do that, $logfile will contain just an asterisk (*).

If you want to display that asterisk, you must quote the variable reference or the wildcard will be expanded:

printf “%s\n” “$logfile”

Or:

echo “$logfile”

(Always quote variable references unless you have a good reason not to.)

12 Toni Kukul October 8, 2010 at 5:47 pm

To read a file into an array it’s possible to use the readarray or mapfile bash built-ins.
readarray < filename
or
mapfile < filename

File is read into MAPFILE variable by default.

13 Anderson Venturini February 28, 2012 at 6:08 am

Thanks a lot! Great tutorial! It was very useful! Congrats!

14 ak March 11, 2012 at 10:50 am

Good Examples. Thank you for hard work and clear explanations. Error in number 12: Suse is omitted from the copied array.

15 Vivek May 30, 2012 at 8:07 pm

Hi,

I need to use cntrC inside my shell script. Here is an example:

run some commands
cntLc
run some more commands

How can I have my shell script generate cntrC without me typing cnrlC?

Vivek.

16 Chris F.A. Johnson May 31, 2012 at 12:21 pm

Vivek, what do you really want to do?

17 Vivek May 31, 2012 at 8:54 pm

Chris, I need to run a script which has a command which gives a running output. I need to change the argument to that command for example from 1 to 10.
Example:
for a in $(seq 1 10)
do

done

Now gives a running output.
Now when a=1, the command is running.
I want to send cntrlC to the command so that ends after lets say 100 seconds and starts.

Vivek.

18 Chris F.A. Johnson June 1, 2012 at 12:23 pm

Vivek, what does this have to do with arrays?

for n in {1..10}
do
: whatever
done &

read && kill “$!”

19 Dennis Dashkevich July 12, 2012 at 3:09 pm

More accurately, the length of the Nth element in an array will give the statement with the N-1 index, i.e. ${#arrayname[N-1]}.

Thanks for the tutorial! It’s really great!

20 h October 29, 2012 at 1:25 am

white space in elements not getting eliminated even though quotes are used

21 Josh January 2, 2013 at 5:41 pm

How about “test to see if value is in array” example?

Below is a small function for achieving this. The search string is the first argument and the rest are the array elements:

containsElement () {
local e
for e in “${@:2}”; do [[ "$e" == "$1" ]] && return 0; done
return 1
}
A test run of that function could look like:

$ array=(“something to search for” “a string” “test2000″)
$ containsElement “a string” “${array[@]}”
$ echo $?
0
$ containsElement “blaha” “${array[@]}”
$ echo $?
1

22 Chris F.A. Johnson January 2, 2013 at 7:23 pm

Josh, there’s no need for a loop:

arraycontains() #@ USAGE: arraycontains STRING ARRAYNAME [IFS]
{
local string=$1 array=$2 localarray IFS=${3:-:}
eval “localarray=( \”\${$array[@]}\” )”
case “$IFS${localarray[*]}$IFS” in
*”$IFS$string$IFS”*) return ;;
*) return 1 ;;
esac
}

23 Chris F.A. Johnson January 8, 2013 at 6:41 pm

I have posted a number of functions for manipulating arrays at http://cfajohnson.com/shell/arrays/

24 Angelo January 23, 2013 at 6:32 am

As a historical note: SuSE has a lower-case “u” and the rest upper-case because it originally stood for “Software und System-Entwicklung”, meaning “Software and systems development”. (Ref: http://en.wikipedia.org/wiki/SuSE)

25 Angelo January 23, 2013 at 9:34 am

I’m a fan of clear code that is easy to read, but was curious whether Mr. Johnson’s arraycontains method had an efficiency benefit (in spite of its more obfuscated nature) over Josh’s (which is almost exactly the method I had been using). I can’t get it to work at all. Maybe I’m missing something, but in case I’m not, maybe I can save someone else the wasted effort in going down this same road.

Here is my test of Chris Johnson’s code:

#!/bin/bash
arraycontains() { #@ USAGE: arraycontains STRING ARRAYNAME [IFS]
local string=$1 array=$2 localarray IFS=${3:-:}
eval “localarray=( \”\${$array[@]}\” )”
case “$IFS${localarray[*]}$IFS” in
*”$IFS$string$IFS”*) return ;;
*) return 1 ;;
esac
}

echo -en “String test 1: ”
one=(“and” “this” “is” “another” “test”)
if arraycontains “something” “${one[@]}”
then
echo “TRUE, but should be FALSE”
else
echo “OK”
fi

echo -en “String test 2: ”
if arraycontains “another” “${one[@]}”
then
echo “OK”
else
echo “FALSE, but should be TRUE”
fi

echo -en “Numeric test: ”
two=(1 2 3 4 5)
arraycontains “5″ “${two[@]}”
echo $?

echo -en “Quoted-numeric test: ”
three=(“1″ “2″ “3″ “4″ “5″)
arraycontains “6″ “${three[@]}”
echo $?

Here is the output:

$ sh test-contains.sh
String test 1: OK
String test 2: FALSE, but should be TRUE
Numeric test: ./test-contains.sh: line 4: ${1[@]}: bad substitution
1
Quoted-numeric test: ./test-contains.sh: line 4: ${1[@]}: bad substitution
1

Besides giving the error message when passed a numeric array, it always returns FALSE (1). On investigation I discovered that the “eval” line is not working; localarray is always blank (so no wonder it always returns false).

I ran this script with BASH 3.00.16 and 4.2.20 and got the same result.

26 Heriel Uronu@udom April 30, 2013 at 7:18 am

yeah… am well and much clear on array in linux command..
wel done stay blessed,

27 x31eq July 17, 2013 at 10:49 am

The second part of Example 10 is especially wrong because of the quoting issue. It means ${Unix[1]} is Red instead of Red hat. The correct way is

Unix=(“${Unix[@]:0:$pos}” “${Unix[@]:$(($pos + 1))}”)

28 Hans November 29, 2013 at 1:49 pm

The best guide on Bash arrays I have ever found!

Thank you.

29 mug896 January 2, 2014 at 6:31 am

To read the file as lines into an array use double quote

fileContents=( “$(cat sunflower.html)” )

for line in “${fileContents[@]}”
do
echo “$line”
done

30 Chris F.A. Johnson January 2, 2014 at 11:57 am

mug896,
That will not read the file line by line; it will read it word by word. All whitespace in the file will act as delimiters.

And you don’t need a loop to print out the array:

printf ‘%s\n’ “${fileContents[@]}”

31 Chris F.A. Johnson January 2, 2014 at 2:10 pm

My mistake, mug896; your code will read the file into a single element of the array. You can see that by:

printf ‘%s\n’ “${fileContents[0]}”

If you had done

fileContents=( $(cat sunflower.html) ) ## no quotes

It would have read each word into a separate element of the array.

32 Offirmo January 9, 2014 at 8:21 am

Very nice, but “iteration on an array” is missing !

33 Erick January 24, 2014 at 5:43 pm

Thanks a lot!

34 Robert Vila February 23, 2014 at 10:57 pm

What do you do when a bash script doesn’t accept arrays?

Error messages:
>>>> “declare: not found”
or
>>>> “Unix[0]=Debian: not found”

35 Chris F.A. Johnson February 25, 2014 at 3:14 pm

Robert, make sure you are using bash to interpret the script.

36 Robert Mark Bram February 27, 2014 at 8:00 pm

Your second example in “10. Remove an Element from an Array” is wrong because you are not enclosing the array parts in quotes – so ‘Red Hat’ becomes two elements.

Here it is fixed up with proofs.

Fri Feb 28 – 12:53 PM > Unix=(‘Debian’ ‘Red hat’ ‘Ubuntu’ ‘Suse’ ‘Fedora’ ‘UTS’ ‘OpenLinux’);
Fri Feb 28 – 12:53 PM > echo ${#Unix[@]}
7
Fri Feb 28 – 12:53 PM > pos=3
Fri Feb 28 – 12:53 PM > echo ${Unix[$pos]}
Suse
Fri Feb 28 – 12:53 PM > Unix=(“${Unix[@]:0:$pos}” “${Unix[@]:$(($pos + 1))}”)
Fri Feb 28 – 12:53 PM > echo ${Unix[$pos]}
Fedora
Fri Feb 28 – 12:53 PM > echo ${Unix[@]}
Debian Red hat Ubuntu Fedora UTS OpenLinux
Fri Feb 28 – 12:53 PM > echo ${#Unix[@]}
6
Fri Feb 28 – 12:53 PM > for index in “${!Unix[@]}” ; do printf “%4d: %s\n” $index “${Unix[$index]}” ; done
0: Debian
1: Red hat
2: Ubuntu
3: Fedora
4: UTS
5: OpenLinux

37 ian fleming March 13, 2014 at 12:37 pm

An alternate, perhaps simpler, method for removing an element, is to reassign Unix (making sure we include the quotes, as per previous post) from the remaining elements in the array (after unsetting):
unset Unix[2]
Unix=( “${Unix[@]” )

Example:
—– $ Unix=(‘Debian’ ‘Red Hat’ ‘Ubuntu’ ‘SuSE’);
—– $ echo “len: ${#Unix[@]}”; for ((i=0;i<4;i++)); do printf "%d %s\n" $i "${Unix[$i]}"; done
len: 4
0 Debian
1 Red Hat
2 Ubuntu
3 SuSE
—– $ unset Unix[2]
—– $ echo "len: ${#Unix[@]}"; for ((i=0;i<4;i++)); do printf "%d %s\n" $i "${Unix[$i]}"; done
len: 3
0 Debian
1 Red Hat
2
3 SuSE
—– $ Unix=( "${Unix[@]}" )
—– $ echo "len: ${#Unix[@]}"; for ((i=0;i<4;i++)); do printf "%d %s\n" $i "${Unix[$i]}"; done
len: 3
0 Debian
1 Red Hat
2 SuSE
3

(note that my loop runs past the end of the array after shortening it )

38 Choperro April 15, 2014 at 5:43 pm

>>>There is no “DECLARED” maximum limit to the size of an array, …..

39 Choperro April 16, 2014 at 3:03 pm

I need to quote, don’t you?
Unix=( “${Unix[@]:0:$pos}” “${Unix[@]:$(($pos + 1)” )})

40 Choperro April 16, 2014 at 3:24 pm

Also. in 11
declare -a patter=( “${Unix[@]/Red*/}” )
It doesn’t remove array elements, it removes the first occurrence that satisfies the regular expression inside each element in the array.

Leave a Comment

Previous post:

Next post: