Trying to sort on two fields, second then first
A key specification like -k2
means to take all the fields from 2 to the end of the line into account. So Villamor 44
ends up before Villamor 50
. Since these two are not equal, the first comparison in sort -k2 -k1
is enough to discriminate these two lines, and the second sort key -k1
is not invoked. If the two Villamors had had the same age, -k1
would have caused them to be sorted by first name.
To sort by a single column, use -k2,2
as the key specification. This means to use the fields from #2 to #2, i.e. only the second field.
sort -k2 -k3 <people.txt
is redundant: it's equivalent to sort -k2 <people.txt
. To sort by last names, then first names, then age, run the following command:
sort -k2,2 -k1,1 <people.txt
or equivalently sort -k2,2 -k1 <people.txt
since there are only these three fields and the separators are the same. In fact, you will get the same effect from sort -k2,2 <people.txt
, because sort
uses the whole line as a last resort when all the keys in a subset of lines are identical.
Also note that the default field separator is the transition between a non-blank and a blank, so the keys will include the leading blanks (in your example, for the first line, the first key will be "Emily"
, but the second key " Bedford"
. Add the -b
option to strip those blanks:
sort -b -k2,2 -k1,1
It can also be done on a per-key basis by adding the b
flag at the end of the key start specification:
sort -k2b,2 -k1,1 <people.txt
But something to bear in mind: as soon as you add one such flag to the key specification, the global flags (like -n
, -r
...) no longer apply to them so it's better to avoid mixing per-key flags and global flags.
With GNU sort
you do it like this, not sure about MacOS:
sort -k2,2 -k1 <people.txt
Update according to comment. Quoted from man sort
:
-k, --key=KEYDEF
sort via a key; KEYDEF gives location and type
KEYDEF is F[.C][OPTS][,F[.C][OPTS]] for start and stop position, where
F is a field number and C a character position in the field; both are
origin 1, and the stop position defaults to the line's end.