Please enable JavaScript eh!

 ⌘ Web Mechanic ⌘ 

Bash Scripting


Sorting Arrays

In Bash, there is no magic built-in that can sort arrays for us.

First we need to declare an array:

declare -a MyArray

This does not produce any output but note the small 'a' to distinguish this from an ordinary variable.

To populate the array, we can do this manually if we know the values already. We'll use a simple CD list for example.

declare -a MyTunes
Title="2CELLOS - In2ition (2013)"
MyTunes=(
"13 Benedictus.flac"
"01 Oh, Well.flac"
"02 We Found Love.flac"
"04 Every Breath You Take.flac"
"05 Supermassive Black Hole.flac"
"06 Technical Difficulties.flac"
"08 Bang Bang.flac"
"09 Voodoo People.flac"
"10 Candle in the Wind.flac"
"07 Clocks.flac"
"11 Orient Express.flac"
"12 Il Libro Dell'Amore.flac"
"03 Highway to Hell.flac"
)

Note they are NOT in the correct track order, so how do we sort that?

First we try echo, piping the result to sort:

clear
echo "Using 'echo' ..."
echo "$Title"
echo "${MyTunes[@]}" | sort
Using 'echo' ...
2CELLOS - In2ition (2013)
13 Benedictus.flac 01 Oh, Well.flac 02 We Found Love.flac 04 Every Breath You Take.flac 05 Supermassive Black Hole.flac 06 Technical Difficulties.flac 08 Bang Bang.flac 09 Voodoo People.flac 10 Candle in the Wind.flac 07 Clocks.flac 11 Orient Express.flac 12 Il Libro Dell'Amore.flac 03 Highway to Hell.flac

Hmmm. Not so good. Try printf:

clear
echo "Using 'printf' ..."
echo "$Title"
printf "%s\n" "${MyTunes[@]}" | sort
Using 'printf' ...
2CELLOS - In2ition (2013)
01 Oh, Well.flac
02 We Found Love.flac
03 Highway to Hell.flac
04 Every Breath You Take.flac
05 Supermassive Black Hole.flac
06 Technical Difficulties.flac
07 Clocks.flac
08 Bang Bang.flac
09 Voodoo People.flac
10 Candle in the Wind.flac
11 Orient Express.flac
12 Il Libro Dell'Amore.flac
13 Benedictus.flac

Much better, and correct to boot!

We had to have a leading '0' in the track numbers to sort correctly (lexicographic)

Using the example array from here.

declare -a SQLBooks=(
"Definitive Guide to SQLite 2E (The)"
"Practical SQL Handbook 4E (The)"
"Joe Celko's SQL For Smarties: Advanced SQL Programming 2E"
"Joe Celko's Data & Databases: Concepts In Practice"
"Database Design for Mere Mortals"
"SQL Queries for Mere Mortals"
"Using SQLite"
"Joe Celko's SQL Puzzles and Answers 2E"
)
printf "%s\n" "${SQLBooks[@]}" | sort

Again, just what we wanted:

Database Design for Mere Mortals
Definitive Guide to SQLite 2E (The)
Joe Celko's Data & Databases: Concepts In Practice
Joe Celko's SQL For Smarties: Advanced SQL Programming 2E
Joe Celko's SQL Puzzles and Answers 2E
Practical SQL Handbook 4E (The)
SQL Queries for Mere Mortals
Using SQLite

Sort Numbers

If your array elements are integers, we can tell sort to accommodate that using -n option.

echo "Sorting numbers"
declare -a MyNumbs=(12 5 78 1 8 0 42)
IFS=$'\n' # Internal Field Separator
MyNumbsSorted=($(sort -n <<< "${MyNumbs[*]}"))
unset IFS
echo "${MyNumbsSorted[@]}"

Surprisingly ...

Sorting numbers
0 1 5 8 12 42 78

There are a couple of bashisms in that bit of code:

  • setting and unsetting the IFS
  • assign an array (variable) to result of a command
  • redirecting input with <<<

    We can also use a loop to walk through the array:

    echo "Number looping ..."
    for n in ${MyNumbsSorted[*]}; do
    	echo $n
    done
    
    Number looping ...
    0
    1
    5
    8
    12
    42
    78