Sort comma-separated fields on each line by numeric value
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
.
Related videos on Youtube
sij
Updated on September 18, 2022Comments
-
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 almost 10 yearsWhat doesn't work? What is the desired output?
-
Bratchley almost 10 yearsThe
-t
specifies what separates fields, butsort
re-orders rows of data. It just references fields in determining what value to sort by. -
Stéphane Chazelas almost 10 years
tr , '\n' < a | sort -n | paste -sd, -
-
sij almost 10 years@Stéphane Chazelas You sir, are really great
-
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 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 almost 7 years
paste -sd , -
would be better thantr "\b" ,
-
Michael Douma over 3 yearsObviously, this also makes a nice one-liner. Here, I changed the delimited to a mid-dot "·" ....
-
Michael Douma over 3 yearscat file.... | perl -F'·' -anle 'BEGIN { $" = "·" }; print "@{[sort {$a cmp $b} @F]}";'
-
Michael Douma over 3 yearsand did a string compare, not numbers.