Bash Arrays

 in

If you're used to a "standard" *NIX shell you may not be familiar with bash's array feature. Although not as powerful as similar constructs in the P languages (Perl, Python, and PHP) and others, they are often quite useful.

Bash arrays have numbered indexes only, but they are sparse, ie you don't have to define all the indexes. An entire array can be assigned by enclosing the array items in parenthesis:

  arr=(Hello World)
Individual items can be assigned with the familiar array syntax (unless you're used to Basic or Fortran):
  arr[0]=Hello
  arr[1]=World
But it gets a bit ugly when you want to refer to an array item:
  echo ${arr[0]} ${arr[1]}
To quote from the man page:
The braces are required to avoid conflicts with pathname expansion.

In addition the following funky constructs are available:

  ${arr[*]}         # All of the items in the array
  ${!arr[*]}        # All of the indexes in the array
  ${#arr[*]}        # Number of items in the array
  ${#arr[0]}        # Length of item zero
The ${!arr[*]} is a relatively new addition to bash, it was not part of the original array implementation.

The following example shows some simple array usage (note the "[index]=value" assignment to assign a specific index):

#!/bin/bash

array=(one two three four [5]=five)

echo "Array size: ${#array[*]}"

echo "Array items:"
for item in ${array[*]}
do
    printf "   %s\n" $item
done

echo "Array indexes:"
for index in ${!array[*]}
do
    printf "   %d\n" $index
done

echo "Array items and indexes:"
for index in ${!array[*]}
do
    printf "%4d: %s\n" $index ${array[$index]}
done
Running it produces the following output:
Array size: 5
Array items:
   one
   two
   three
   four
   five
Array indexes:
   0
   1
   2
   3
   5
Array items and indexes:
   0: one
   1: two
   2: three
   3: four
   5: five

Note that the "@" sign can be used instead of the "*" in constructs such as ${arr[*]}, the result is the same except when expanding to the items of the array within a quoted string. In this case the behavior is the same as when expanding "$*" and "$@" within quoted strings: "${arr[*]}" returns all the items as a single word, whereas "${arr[@]}" returns each item as a separate word.

The following example shows how unquoted, quoted "*", and quoted "@" affect the expansion (particularly important when the array items themselves contain spaces):

#!/bin/bash

array=("first item" "second item" "third" "item")

echo "Number of items in original array: ${#array[*]}"
for ix in ${!array[*]}
do
    printf "   %s\n" "${array[$ix]}"
done
echo

arr=(${array[*]})
echo "After unquoted expansion: ${#arr[*]}"
for ix in ${!arr[*]}
do
    printf "   %s\n" "${arr[$ix]}"
done
echo

arr=("${array[*]}")
echo "After * quoted expansion: ${#arr[*]}"
for ix in ${!arr[*]}
do
    printf "   %s\n" "${arr[$ix]}"
done
echo

arr=("${array[@]}")
echo "After @ quoted expansion: ${#arr[*]}"
for ix in ${!arr[*]}
do
    printf "   %s\n" "${arr[$ix]}"
done
When run it outputs:
Number of items in original array: 4
   first item
   second item
   third
   item

After unquoted expansion: 6
   first
   item
   second
   item
   third
   item

After * quoted expansion: 1
   first item second item third item

After @ quoted expansion: 4
   first item
   second item
   third
   item

______________________

Mitch Frazier is an Associate Editor for Linux Journal.

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Script fails?

EvilDave's picture

The example script fails on my Solaris 9 server using GNU Bash-2.05. Of course you do mention that the ${!array[*]} is fairly new so it appears not to be in my version of bash. Posting what version you are using would be helpful.

Here's the output I got.

#
Array size: 5
Array items:
one
two
three
four
five
Array indexes:
Array items and indexes:

Thanks!

SQLITE

Amr El-Sharnoby's picture

Hello,
Thanks for this article, Using bash arrays is MUST to avoid using tmp files and unnessary loops in some cases ...
But for large amount of data, I'd highly recommend using sqlite databases which is much faster and allows better functions ...

Think big

Mitch Frazier's picture

When I have a lot of data to store I use a Sun Fire X4500 server with 48 Terabytes of attached storage. What I like most about this is that it's a one to one swap for using bash.

Geez...

Mitch Frazier is an Associate Editor for Linux Journal.

Array in bash is really

Jadu Saikia's picture

Array in bash is really helpful. Here is how we can join two arrays in bash

http://unstableme.blogspot.com/2008/12/join-two-arrays-in-bash-script.html

what about speed

Anonymous's picture

hmm, I've tried once to use bash arrays in a simple script, which looked for specified strings in all cvs revisions of a file. But it seemed to work rather slowly.

Trolls

EvilDave's picture

So he tried it "ONCE" and decided it was slow? Hmmmm...

Pretty weak

Mitch Frazier's picture

Since you don't really give us any details to support your assertion: no source for your script and no details of other bash based implementations that proved faster, I have to assume that the slowness was related to CVS, or to searching, or possibly to bash in general, but I doubt it had anything do with bash arrays.

Mitch Frazier is an Associate Editor for Linux Journal.

speed

Kevin Cantu's picture

That's clearly just a troll. Bash is useful and the author doesn't need to justify its relevance. :D

Webinar
One Click, Universal Protection: Implementing Centralized Security Policies on Linux Systems

As Linux continues to play an ever increasing role in corporate data centers and institutions, ensuring the integrity and protection of these systems must be a priority. With 60% of the world's websites and an increasing share of organization's mission-critical workloads running on Linux, failing to stop malware and other advanced threats on Linux can increasingly impact an organization's reputation and bottom line.

Learn More

Sponsored by Bit9

Webinar
Linux Backup and Recovery Webinar

Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.

In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.

Learn More

Sponsored by Storix