Skip to main content

1. Arrays

Arrays are variables that hold more than one value at a time.

  1. 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[*]}
  2. 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" $count

    To 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.

  3. 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: $*, $@, "$*", "$@".

  4. 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.

  5. 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
  6. Adding elements to the end of an array:

    foo=(a b c)
    echo ${foo[@]}
    foo+=(d e f)
    echo ${foo[@]}
  7. 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
  8. 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.

  9. 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[@]}
  10. 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"]}
Loading asciinema cast...