2

I have a list like this:

1,kg,cat
1000,g,dog
20,g,apple

And I want to sort it by weight. 1 kg and 1000 g would be the same, so I'd like to have my rows sorted by weight. My data set is larger and has different units, and I want to know how to sort it so that the code can recognize that 3000 g is larger than 1 kg and so on.

  • I edited your question to fix the format and removed the spaces you had in your example. I assumed you only added them for clarity. If those spaces are actually present in your text file, please edit and return them. – terdon Mar 29 '15 at 1:21
  • Also, what units does your file actually have? How many different units does this need to deal with? – terdon Mar 29 '15 at 1:35
  • just grams (g) and kilograms (kg) – XY g Mar 29 '15 at 2:06
4

If your file is too large to hold in memory, you could do:

$ awk -F, -v OFS="," '$2=="kg"{$1=1000*$1}1;' file | sort -n | 
    awk -F, -v OFS="," '$2=="kg"{$1=$1/1000}1;'
1000,g,dog
1,kg,cat
20,g,apple
4

I prefer the variant of not changing the existing data , but adding the sort criteria as new column, and removing that auxiliary sorting field at the end of the pipe:

awk -F, 'BEGIN {u["kg"]=1000; u["g"]=1}; {print $1*u[$2], $0}' file |
    sort -n | cut -d" " -f2-
2

You might be better off converting the units in the file, sorting them and using the resulting stored file.

sed -r 's/^([0-9]+),kg/\1000,g/' $file | sort -n

sed doesn't understand math, so if you have non-intigers you'll have to use something else. The following does the fast parse with sed, but uses bc to do actual math if needed.

sed -r 's/^([0-9]+),kg/\1000,g/;s/^([0-9\.]+),kg/echo $(echo \1*1000 | bc),g/e'
  • This changes the units. You will print everything in grams. – terdon Mar 29 '15 at 11:42

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.