12

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"

6
  • What doesn't work? What is the desired output?
    – psimon
    Commented Jul 2, 2014 at 14:46
  • 1
    The -t specifies what separates fields, but sort re-orders rows of data. It just references fields in determining what value to sort by.
    – Bratchley
    Commented Jul 2, 2014 at 14:46
  • 5
    tr , '\n' < a | sort -n | paste -sd, - Commented Jul 2, 2014 at 15:10
  • @Stéphane Chazelas You sir, are really great
    – sij
    Commented Jul 2, 2014 at 15:39
  • 3
    @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. Commented Jul 2, 2014 at 18:18

4 Answers 4

13

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).

7

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" ,
1
  • paste -sd , - would be better than tr "\b" , Commented May 26, 2017 at 23:10
6

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

2

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.

3
  • Obviously, this also makes a nice one-liner. Here, I changed the delimited to a mid-dot "·" .... Commented Dec 3, 2020 at 19:40
  • cat file.... | perl -F'·' -anle 'BEGIN { $" = "·" }; print "@{[sort {$a cmp $b} @F]}";' Commented Dec 3, 2020 at 19:40
  • and did a string compare, not numbers. Commented Dec 3, 2020 at 19:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .