0

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!!

5
  • What are you sorting on, "Matched" ? Commented May 26, 2012 at 8:23
  • 1
    Use python would be my advice! IMHO you've left the sweet spot of bash. Commented May 26, 2012 at 8:58
  • @NickCraig-Wood: Obviously you don't know bash. Commented May 26, 2012 at 10:31
  • I think what Nick meant is: doing this kind of things in python is lot easier. Cheers!! Commented May 26, 2012 at 19:55
  • I would like to see what is more easy than to stick together these 4 commands. Commented May 26, 2012 at 20:25

3 Answers 3

3

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
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks Michał, it worked just fine. Sorting array or output - either way works for me. All I needed to print the formatted result. Cheers!!
1
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.

1 Comment

agreed on "semicolon" thing; that was the very first version and I was still deciding what to do. Thanks for the code - I actually got an idea to use this elsewhere. Just one thing: the seq part could be shorten like this: ${!WCUM[@]}. Cheers!!
0

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"

Comments

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.