Sort comma-separated fields on each line by numeric value

37,370

Solution 1

sort operates on entire lines. By default, it sorts on the entire contents of that line, but -k can be used to sort on one or more fields within those lines. -t can be used to change the delimiter between fields. I can't think of a case where using -t without also using -k makes any sense.

Your second command, which is equivalent to:

printf "%s\n%s\n" "110,20,30,13" "kill,gill,burger" | sort -t',' -n

produces:

kill,gill,burger
110,20,30,13

Which is what I'd expect. -t',' has no effect because it's changing the field delimiter when you haven't told sort to operate on individual fields, and so k is sorted before 1 because its numerical value is 0 (and you requested numerical ordering using -n).

Solution 2

Sort works on a per-line basis, not on fields within a line.

By default, it sorts based on the first character on the line and goes on from there. But you can also sort on "keys" other than at the beginning. This is useful when you want to sort on last name, or a numeric value at the end of the line, or so on. That's what the -t flag is for — it won't break up individual lines and sort within them.

If that's what you want to do, see Sort fields inline

Solution 3

Sorting by commas is somewhat possible:

echo "a,b,z,sa,b,z,a,d,2,4a,a,dx" | tr , "\n" | sort

Outputs

2
4a
a
a
a
b
b
d
dx
sa
z
z

And if you want it back on one line:

echo "a,b,z,sa,b,z,a,d,2,4a,a,dx" | tr , "\n" | sort | tr "\n" ,

Solution 4

It will be easier with perl:

$ perl -F',' -anle '
    BEGIN { $" = "," }
    print "@{[sort {$a <=> $b} @F]}"
' file 
13,20,30,110
kill,gill,burger

This only sort lines which contains numbers. If you want sort lines contains string like sort -n does, try:

$ $ perl -MPOSIX=isdigit -F',' -anle '
BEGIN { $" = "," }
print "@{[ sort { isdigit($a)
              ? ($a <=> $b)
              : ($a cmp $b)
              } @F
        ]}"
' file
13,20,30,110
burger,gill,kill

This approach still only works if like contains only string,failed with like contains mixed string, numbers like kill,gill,20.

Share:
37,370

Related videos on Youtube

sij
Author by

sij

Updated on September 18, 2022

Comments

  • sij
    sij over 1 year

    I tried this:

    $ echo "2,3435,1" | sort -n
    2,3435,1
    
    $ sort -t',' -n test_sort.txt
    kill,gill,burger
    110,20,30,13
    
    $ cat test_sort.txt
    110,20,30,13
    kill,gill,burger
    

    Why doesn't my sort command work?

    My desired sort command should work like this:

    $sort -t',' -n test_sort.txt  
    110,13,20,30,burger,gill,kill
    

    ANSWER : tr , '\n' < a | sort -n | paste -sd, -

    "Thanks to Stéphane Chazelas"

    • psimon
      psimon almost 10 years
      What doesn't work? What is the desired output?
    • Bratchley
      Bratchley almost 10 years
      The -t specifies what separates fields, but sort re-orders rows of data. It just references fields in determining what value to sort by.
    • Stéphane Chazelas
      Stéphane Chazelas almost 10 years
      tr , '\n' < a | sort -n | paste -sd, -
    • sij
      sij almost 10 years
      @Stéphane Chazelas You sir, are really great
    • David Conrad
      David Conrad almost 10 years
      @StéphaneChazelas You should post that as an answer. Answering questions in comments (something I've been guilty of in the past) is not desirable.
    • Mike
      Mike over 7 years
      @DavidConrad and worst even, the OP edit the question to put the answer in it... SIJAR you can post the answer instead editing the question.
  • Stéphane Chazelas
    Stéphane Chazelas almost 7 years
    paste -sd , - would be better than tr "\b" ,
  • Michael Douma
    Michael Douma over 3 years
    Obviously, this also makes a nice one-liner. Here, I changed the delimited to a mid-dot "·" ....
  • Michael Douma
    Michael Douma over 3 years
    cat file.... | perl -F'·' -anle 'BEGIN { $" = "·" }; print "@{[sort {$a cmp $b} @F]}";'
  • Michael Douma
    Michael Douma over 3 years
    and did a string compare, not numbers.