MacUsers
MacUsers

Reputation: 2229

sorting a "key/value pair" array in bash

How do I sort a "python dictionary-style" array e.g. ( "A: 2" "B: 3" "C: 1" ) in bash by the value? I think, this code snippet will make it bit more clear about my question.

State="Total 4 0 1 1 2 0 0"
W=$(echo $State | awk '{print $3}')
C=$(echo $State | awk '{print $4}')
U=$(echo $State | awk '{print $5}')
M=$(echo $State | awk '{print $6}')
WCUM=( "Owner: $W;" "Claimed: $C;" "Unclaimed: $U;" "Matched: $M" )
echo ${WCUM[@]}

This will simply print the array: Owner: 0; Claimed: 1; Unclaimed: 1; Matched: 2

How do I sort the array (or the output), eliminating any pair with "0" value, so that the result like this:

Matched: 2; Claimed: 1; Unclaimed: 1

Thanks in advance for any help or suggestions. Cheers!!

Upvotes: 0

Views: 2407

Answers (3)

user unknown
user unknown

Reputation: 36229

echo -e ${WCUM[@]} | tr ';' '\n' | sort -r -k2 | egrep -v ": 0$"

Sorting and filtering are independent steps, so if you only like to filter 0 values, it would be much more easy.

Append an

 | tr '\n' ';'

to get it to a single line again in the end.

nonull=$(for n in ${!WCUM[@]}; do echo ${WCUM[n]} | egrep -v ": 0;"; done | tr -d "\n")

I don't see a good reason to end $W $C $U with a semicolon, but $M not, so instead of adapting my code to this distinction I would eliminate this special case. If not possible, I would append a semicolon temporary to $M and remove it in the end.

Upvotes: 1

choroba
choroba

Reputation: 241838

Another attempt, using some of the bash features, but still needs sort, that is crucial:

#! /bin/bash
State="Total 4 1 0 4 2 0 0"
string=$State
for i in 1 2 ; do        # remove unnecessary fields
    string=${string#* }
    string=${string% *}
done

# Insert labels
string=Owner:${string/ /;Claimed:}
string=${string/ /;Unclaimed:}
string=${string/ /;Matched:}

# Remove zeros
string=(${string[@]//;/; })
string=(${string[@]/*:0;/})
string=${string[@]}

# Format
string=${string//;/$'\n'}
string=${string//:/: }

# Sort
string=$(sort -t: -nk2 <<< "$string")
string=${string//$'\n'/;}
echo "$string"

Upvotes: 0

Michał Trybus
Michał Trybus

Reputation: 11784

Quick and dirty idea would be (this just sorts the output, not the array):

echo ${WCUM[@]} | sed -e 's/; /;\n/g' | awk -F: '!/ 0;?/ {print $0}' | sort -t: -k 2 -r | xargs

Upvotes: 3

Related Questions