How to sort IP addresses using the GNU sort utility.
Here’s the invocation that works. It’s explained in the long answer that follows.
sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4
A sharp-eyed reader notes that the
sort binary included with GNU
coreutils version 7.0 and higher accepts a new option: –version-sort
(-V, –sort=version). Since IPv4 addresses look like software version
numbers, the new option will reliably sort them:
Since not all field-based sorting is that simple, I’ll continue with my original explanation – but for sorting IPv4 addresses the -V option is simplest.
More than once I’ve been confronted with a list of IP addresses that I’ve wanted to sort into numeric order. Trouble is, the dotted-quad notation isn’t sort-friendly. Consider the following raw list of addresses.
$ cat addresses.txt 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11
sort will rely on alphabetic order, which certainly
won’t do what you want:
$ sort addresses.txt 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11
There are so many mistakes in this ordering I’m not even going to try to list them all.
The situation is only marginally improved when using the
$ sort -n addresses.txt 18.104.22.168 22.214.171.124 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11
The first set of numbers in each dotted-quad sort correctly—5 preceeds 19, and 129 is at the tail end—but the internal numbering still gets improper treatment. 18.104.22.168 is listed prior to 22.214.171.124 because 220 is alphabetically prior to 24. Likewise the two 19.20.x.x addresses are mixed up because 203 is alphabetically prior to 21.
The solution is to tell
sort to order the list numerically,
considering each address as a set of four numeric fields, each separated
by a dot.
$ sort -n -t . -k 1,1 -k 2,2 -k 3,3 -k 4,4 addresses.txt 126.96.36.199 188.8.131.52 184.108.40.206 220.127.116.11 18.104.22.168 22.214.171.124
In English, you’re saying, Yo,
sort! I’ve got here a list of numbers
-n), but each item in the list consists of some subnumbers, fields
set apart from the others by a dot (
-t .). Sort first by the first
field, and only the first field (
-k 1,1), then by the second and only
the second (
-k 2,2), and so on (
-k 3,3 -k 4,4).
Or, as I mentioned above, just use
There are other widely used data with mixed numeric and alphabetic fields can be sorted with similar techniques.
getent utility will sort group information by GID, but the
sorting is done per-source. If you have an extensive
file and a large network-provided group database (from, e.g.,
LDAP), the groups are not interleaved. Here
sort can do its magic:
getent group | sort -n -t: -k 3,3
When returning the
getent sorts by username not UID,
making sort even more useful:
getent passwd | sort -n -t: -k 3,3