48

How can I sort input such as this using the sort command? I would like the numbers to be sorted numerically before the letters.

10
11
12
1
13
14
15
16
17
18
19
20
21
2
22
3
4
5
6
7
8
9
X
Y
3
  • 5
    Sort them how, exactly? That seems like a completely arbitrary sort order. And those aren't numbers. Also, you forgot chrM. Please edit your question and clarify. What exactly are you trying to do?
    – terdon
    Commented Apr 1, 2017 at 14:13
  • No attempt and unclear what you're asking. Please add your desired output and what you tried to obtain it.
    – simlev
    Commented Sep 17, 2018 at 10:14
  • 2
    To the other commenters: He wants to sort these numbers numerically, so a 2 would come before 15, if it were alphabetically 2 would come after 15, because 2 comes after 1.
    – Jake
    Commented Feb 28, 2021 at 22:30

3 Answers 3

94

As @terdon noticed, the inclusion of X and Y and the fact that the numbers run from 1 to 22 identifies this as a possible list of human chromosomes (which is why he says that chromosome M (mitochondrial) may be missing).

To sort a list of numbers, one would usually use sort -n:

$ sort -n -o list.sorted list

where list is the unsorted list, and list.sorted will be the resulting sorted list.

With -n, sort will perform a numerical sort on its input. However, since some of the input is not numerical, the result is probably not the intended; X and Y will appear first in the sorted list, not last (the sex chromosomes are usually listed after chromosome 22).

However, if you use sort -V (for "version sorting"), you will actually get what you want:

$ sort -V -o list.sorted list
$ cat list.sorted
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
X
Y

This will probably still not work if you do add M as that would be sorted before X and not at the end (which I believe is how it's usually presented).

3
  • Oh, so the list of values presented in the question is the set to be sorted rather then the intended result of some (apparently arbitrary) sorting? Commented Apr 1, 2017 at 20:25
  • @roaima That is how I interpret it. And if it's chromosomes, they are most likely to be sorted numerically, and then X followed by Y.
    – Kusalananda
    Commented Apr 2, 2017 at 14:21
  • Thanks. It threw me completely; i didn't expect the list to be the raw set, but rather the sorted set. I've tweaked the language in the question a little to try and help clarify that. Commented Apr 2, 2017 at 14:49
4

If you mean they should sort in the 1..22, X, Y, M order, then you can translate those X, Y, M to numbers before sorting and back after sorting:

sed 's/X/23/;s/Y/24/;s/M/25/' < file | sort -n | sed 's/23/X/;s/24/Y/;s/25/M/'

If those numbers are in a zsh array, you can apply an arbitrary sort order using this hack:

k=({1..22} X Y M) v=({01..25})
typeset -A rank=(${k:^v})

unsorted=(22 Y 5 X M 13)
sorted=(/(e'{reply=($unsorted)}'oe'{REPLY=$rank[$REPLY]}'))

Or if the members of $unsorted are unique, use array intersection:

all=({1..22} X Y M)
unsorted=(22 Y 5 X M 13)
sorted=(${all:*unsorted})
-1

you can use

cat number.txt|sort -n
1
  • 7
    See my answer as to why this will probably not generate the correct result. Also, cat is totally unnecessary here.
    – Kusalananda
    Commented Sep 17, 2018 at 10:22

You must log in to answer this question.

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