How can I sort numbers in a unix shell?
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).
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})