2

When I execute the following code, the output of the printf statement appears to show array out of sequence. In the declare statement the Source item is declared before Destination and in the output it's reversed.

YELLOW=$'\e[93m'
declare -A OP=( [Description]="remote to destination" [Source]="/var/www" [Destination]="/foo/bar" [Log]="my.log" [Email]="me@here" );

NO_COLS=`tput cols`
COLS_PER_COL=$(($NO_COLS/3))
PRINT_FORMAT="%"$COLS_PER_COL"s%""s\n"

for i in "${!OP[@]}"; do
    printf $PRINT_FORMAT "$i :" " $YELLOW${OP[$i]}$ENDCOL"
done ;

Output looks like

         Description : remote to destination
         Destination : /foo/bar
              Source : /var/www
                 Log : my.log
               Email : me@here

Can anyone tell me what is happening here? or how I can achieve the proper order according to the array declaration?

  • 3
    Associative arrays have no inherent order. The insertion order is not preserved. – glenn jackman Jan 28 '15 at 3:58
  • That makes sense, although it appears to obey some type of order because it consistently prints the same sequence even if you move the variables around in the declaration. It just so happened that I declared them similar to the output which is why I thought there was something wrong with the code. Problem solved with the answer here... just curious. – dimmech Jan 28 '15 at 14:05
8

Associative array in bash (and in other languages) does not preserve the order of elements in declaration.

You can add another associative array to keep track the order of declaration:

YELLOW=$'\e[93m'
declare -A OP=( [Description]="remote to destination"
                [Source]="/var/www"
                [Destination]="/foo/bar"
                [Log]="my.log"
                [Email]="me@here" )

declare -A IP=( [1]="Description"
                [2]="Source"
                [3]="Destination"
                [4]="Log"
                [5]="Email" );

NO_COLS="$(tput cols)"
COLS_PER_COL="$((NO_COLS/3))"
PRINT_FORMAT="%${COLS_PER_COL}s%s\n"

for i in "${!IP[@]}"; do
  k=${IP[$i]}
  printf "$PRINT_FORMAT" "$k :" " $YELLOW${OP[$k]}$ENDCOL"
done

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.