1

How do I sort an associative array in bash?

For example, I have array in bash:

[0,0]="Max"
[0,1]="25"
[1,0]="Vladimir"
[1,1]="0"
[2,0]="Mayki"
[2,1]="50"

Output must be:

  1. Mayki - 50
  2. Max - 25
  3. Vladimir - 0

I don't know how sort this array.

Additional Info: I parse assoc array from text file ("log.txt")

    #!/bin/bash

declare -A b_array

# Read the file in parameter and fill the array named "array"
getArray() {

    i=0
    w=9

    count=10

    while read line # Read a line
    do
        k=0
        #array[i]=$line # Put it into the array

        #b_array[$i,0]=$(grep -Eo "(http|https)://[a-zA-Z0-9./?=_-]*" <<<"$line") 

        for word in $line;
          do  
                  #echo $k;
                  #echo $word;
                  if [ "$k" = "$w" ]; then
                      if [ $word != "-" ]; then
                        b_array[$i]=$word 
                        i=$(($i + 1))
                      fi 

                  fi 
                  k=$(($k + 1))
            done


    done < $1
}

getArray "log.txt"
7
  • 1
    You're better off using a language with better data structure support. Commented Apr 24, 2015 at 14:53
  • 1
    What does the input actually look like? What does that example array have to do with anything? You aren't creating one like that (bash can't do it). You don't appear to have one like that in the input (though that isn't at all clear). Associative arrays don't have an order so the best you could do is fetch and sort the keys and then loop over that sorted list of keys. Commented Apr 24, 2015 at 15:01
  • It my homework of KPI University Commented Apr 24, 2015 at 15:06
  • The original mission: I need to parse the file and display 10 lines of queries by the number of bytes. Commented Apr 24, 2015 at 15:08
  • 1
    This is a really odd way to use an associative array. One would usually use the name as the key: ([Max]=25 [Mayki]=50 [Vladimir]=0) Commented Apr 24, 2015 at 16:23

2 Answers 2

1

There are a couple of approaches to this problem. One of the easiest is probably to read the pairs of strings into an indexed array and then reverse numeric sort on the number field:

#!/bin/bash

declare -A arr
declare -a sa

arr[0,0]="Max"
arr[0,1]="25"
arr[1,0]="Vladimir"
arr[1,1]="0"
arr[2,0]="Mayki"
arr[2,1]="50"

## convert associative array to 
#  indexed array of string pairs
#  (e.g. "Max - 25", "Mayki - 50" )
for i in ${!arr[@]}; do                         # for each key in ar

    x=${i%,*}                                   # separate x,y values
    y=${i#*,}
    (( y == 1 )) && continue                    # if y == 1, continue

    for j in ${!arr[@]}; do                     # for each key in ar

        _x=${j%,*}                              # separate _x,_y values
        _y=${j#*,}
        ((x != _x)) || ((_y == 0)) && continue  # if x != _x, or _y == 0, continue

        sa+=( "${arr[$i]} - ${arr[$j]}" )       # add combined string to indexed sa

    done
done

sort -r -k3 -n <<<"$(printf "%s\n" "${sa[@]}")" # numeric reverse sort sa on key3

exit 0

Output

$ bash sort_assoc.sh
Mayki - 50
Max - 25
Vladimir - 0
Sign up to request clarification or add additional context in comments.

9 Comments

What errors? I have GNU bash, version 4.3.33 There are other ways to sort the indexed array if that is giving you problems. I checked, also works on GNU bash, version 4.2.37 (oldest I have)
: No such file or directoryh : command not found ': not a valid identifier ar ': not a valid identifier sa : command not found : command not found sort.sh: line 36: syntax error: unexpected end of file -bash-4.1$
What? are you sure you copied/pasted it exactly? Let's change ar to arr to not conflict with the external ar command (which it shouldn't anyway) Try it now.
Sorry, check the code on the server console VPS (4.1). It is still on the virtual machine will try to run (4.3).
Ok, it works perfectly. I've ran in on multiple machines (Archlinux & openSuSE) to confirm. The ar ': not a valid identifier and sa : command not found : command not found sort.sh: line 36 errors make No sense. There is something suspect with your shell interpreter if you are getting those errors. Let me know what you find out.
|
1

I'd probably switch to Perl for such a complicated task, even if it's still doable in bash:

#!/bin/bash

declare -A arr
arr=([0,0]="Max"
     [0,1]="25"
     [1,0]="Vladimir"
     [1,1]="0"
     [2,0]="Mayki"
     [2,1]="50"
     [10,0]=Ivan
     [10,1]=10
    )

indices=( $( (IFS=$'\n' ; echo "${!arr[*]}") | grep ,0 | cut -d, -f1 | sort ) )

for i in "${indices[@]}" ; do
    echo ${arr[$i,0]} ${arr[$i,1]}
done | sort -rnk2

It would be much simpler if you defined the array like

arr=([Max]=25
     [Vladimir]=0
     [Mayki]=50
     [Ivan]=10
    )

for paren in "${!arr[@]}" ; do
    echo $paren ${arr[$paren]}
done | sort -rnk2

6 Comments

I have error: : command not found ': not a valid identifier: arr : command not found : command not found 'est3.sh: line 16: syntax error near unexpected token do 'est3.sh: line 16: `for i in "${indices[@]}" ; do
@МаксимБорисов: What version of bash?
@МаксимБорисов: It should work. Did you copy and paste the code?
@МаксимБорисов: Blocked here :-(
@МаксимБорисов: Can't access either :-(
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.