Bash Arrays
June 19th, 2008 by Mitch Frazier 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]=WorldBut 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 if 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
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
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 the System Administrator at Linux Journal.
Special Magazine Offer -- 2 Free Trial Issues!
Receive 2 free trial issues of Linux Journal as well as instant online access to current and past issues. There's NO RISK and NO OBLIGATION to buy. CLICK HERE for offer
Linux Journal: delivering readers the advice and inspiration they need to get the most out of their Linux systems since 1994.
Sorry, offer available in the US only. International orders, click here.
Subscribe now!
The Latest
Featured Videos
Email is one of the least private and least secure forms of communication, although few people realize this. MixMaster is one way to allow secure, anonymous communication even over the very public medium of email. This tutorial will get you started with MixMaster quickly and easily.
In case you were wondering about the fun side of Linux World Expo, we thought we'd give you a peek at our shenanigans. We at Linux Journal love what we do so much, that we can't help but have a ball wherever we go.
Recently Popular
From the Magazine
September 2008, #173
Feeling a bit like a Thermian? Never give up, never surrender! Someday, you could go from underdog to top dog. Just take a look at a few of the underdogs we highlight in this issue: Mutt, djbdns, Nginix, Gentoo, Xara and the program voted mostly likely to fail just a few years back—Firefox. If Firefox is not radical enough for you, check out Chef Marcel's column for some more alternatives. Having trouble mapping your program data to your relational database? If so, Rueven Lerner shows you some tricks in his At The Forge column.
Need to run GUI applications on your server in the next state? In his Paranoid Penguin column, Mick Bauer shows you how to do it securely. Kyle Rankin keeps hacking and slashing and shows you a few split screen secrets you may not be familiar with. Finally, we all know what happens next February, but only Doc knows what happens afterward.
Delicious
Digg
Reddit
Newsvine
Technorati







what about speed
On July 1st, 2008 Anonymous (not verified) says:
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.
Pretty weak
On July 1st, 2008 Mitch Frazier says:
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 the System Administrator at Linux Journal.
speed
On July 7th, 2008 Kevin Cantu (not verified) says:
That's clearly just a troll. Bash is useful and the author doesn't need to justify its relevance. :D