1. Arrays
Arrays are variables that hold more than one value at a time.
-
Getting started:
a[0]=foo
echo ${a[0]}
days=(Sun Mon Tue Wed Thu Fri Sat)
echo ${days[0]}
echo ${days[*]}
echo $days[*]
echo $days
If no index is given, the first item is returned.
days=([0]=Sun [1]=Mon [2]=Tue [3]=Wed [4]=Thu [5]=Fri [6]=Sat)
echo ${days[*]}
-
Let's see an example that counts files by modification time and shows them in a table. Such a script could be used to determine when a system is most active.
./hours.sh
./hours.sh /usr/bin/
vim hours.sh
hours.sh
#!/bin/bash
# hours: script to count files by modification time
usage () {
echo "usage: ${0##*/} directory" >&2
}
# Check that argument is a directory
if [[ ! -d "$1" ]]; then
usage
exit 1
fi
# Initialize array
for i in {0..23}; do hours[i]=0; done
# Collect data
for i in $(stat -c %y "$1"/* | cut -c 12-13); do
j="${i#0}"
((++hours[j]))
((++count))
done
# Display data
echo -e "Hour\tFiles\tHour\tFiles"
echo -e "----\t-----\t----\t-----"
for i in {0..11}; do
j=$((i + 12))
printf "%02d\t%d\t%02d\t%d\n" \
"$i" \
"${hours[i]}" \
"$j" \
"${hours[j]}"
done
printf "\nTotal files = %d\n" $countTo get the last modification time of the files we use the command
stat
:stat --help | less
stat -c %y *
stat -c %y * | cut -c 12-13
We use the hour of modification as an index for the array.
-
Outputting the entire contents of an array:
animals=("a dog" "a cat" "a fish")
for i in ${animals[*]}; do echo $i; done
for i in ${animals[@]}; do echo $i; done
for i in "${animals[*]}"; do echo $i; done
for i in "${animals[@]}"; do echo $i; done
Notice that this is similar to the behavior of the array of the positional parameters:
$*
,$@
,"$*"
,"$@"
. -
The number of array elements:
a[100]=foo
echo ${#a[@]}
There is only one element in the array.
echo ${#a[100]}
This is the length of the element 100.
Remember that
$#
is the number of positional parameters. -
Finding the subscripts used by an array:
foo=([2]=a [4]=b [6]=c)
for i in "${foo[@]}"; do echo $i; done
for i in "${!foo[@]}"; do echo $i; done
-
Adding elements to the end of an array:
foo=(a b c)
echo ${foo[@]}
foo+=(d e f)
echo ${foo[@]}
-
It is not so hard to sort an array with a little bit of coding:
vim array-sort.sh
array-sort.sh
#!/bin/bash
# array-sort: Sort an array
a=(f e d c b a)
echo "Original array: ${a[@]}"
a_sorted=($(for i in "${a[@]}"; do echo $i; done | sort))
#a_sorted=($(echo "${a[@]}" | tr ' ' "\n" | sort))
echo "Sorted array: ${a_sorted[@]}"./array-sort.sh
-
To delete an array, use the
unset
command:foo=(a b c d e f)
echo ${foo[@]}
unset foo
echo ${foo[@]}
It may also be used to delete single array elements.
foo=(a b c d e f)
echo ${foo[@]}
unset 'foo[2]'
echo ${foo[@]}
Notice that the array element must be quoted to prevent the shell from performing pathname expansion.
-
Notice also that the assignment of an empty value to an array does not empty its contents:
foo=(a b c d e f)
foo=
echo ${foo[@]}
This is because any reference to an array variable without a subscript refers to element zero of the array. For example:
foo=(a b c d e f)
echo ${foo[@]}
foo=A
echo ${foo[@]}
-
Associative arrays use strings rather than integers as array indexes:
declare -A colors
colors["red"]="#ff0000"
colors["green"]="#00ff00"
colors["blue"]="#0000ff"
Associative arrays must be created with declare -A
. Its
elements are accessed in the same way as the integer indexed
arrays:
echo ${colors["green"]}