Hi, I needed to sort some text by IP addresses, and there does not seem to be a good way to do it. They only trick I found was "-n -t. -k1,1 -k2,2 -k3,3 -k4.4" or so, but that is kind of ugly. So I hacked together a patch that adds -I,--ipaddess-sort to sort. It's still incomplete (no IPv6, no manual, possibly configure.in checks needed), but I would work on this if there is a chance that the patch will get added.
The patch below is against 5.97 (actually against 5.97 + Debian unstable patches that make up 5.97-5.2, but I think sort.c is not affected by this). Comments? Best, Norbert P.S.: Please CC, I'm not subscribed. --nk --- src/sort.c~ 2006-11-26 03:57:00.000000000 -0800 +++ src/sort.c 2006-11-26 10:37:04.000000000 -0800 @@ -25,6 +25,8 @@ #include <getopt.h> #include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> #include <signal.h> #include "system.h" #include "error.h" @@ -150,6 +152,7 @@ bool general_numeric; /* Flag for general, numeric comparison. Handle numbers in exponential notation. */ bool month; /* Flag for comparison by month name. */ + bool ipaddress; /* Flag for comparison as ip address. */ bool reverse; /* Reverse the sense of comparison. */ struct keyfield *next; /* Next keyfield to try. */ }; @@ -302,6 +305,7 @@ -g, --general-numeric-sort compare according to general numerical value\n\ -i, --ignore-nonprinting consider only printable characters\n\ -M, --month-sort compare (unknown) < `JAN' < ... < `DEC'\n\ + -I, --ipaddress-sort compare according to IP address value\n\ -n, --numeric-sort compare according to string numerical value\n\ -r, --reverse reverse the result of comparisons\n\ \n\ @@ -353,7 +357,7 @@ exit (status); } -static char const short_options[] = "-bcdfgik:mMno:rsS:t:T:uy:z"; +static char const short_options[] = "-bcdfgik:mMIno:rsS:t:T:uy:z"; static struct option const long_options[] = { @@ -366,6 +370,7 @@ {"key", required_argument, NULL, 'k'}, {"merge", no_argument, NULL, 'm'}, {"month-sort", no_argument, NULL, 'M'}, + {"ipaddress-sort", no_argument, NULL, 'I'}, {"numeric-sort", no_argument, NULL, 'n'}, {"output", required_argument, NULL, 'o'}, {"reverse", no_argument, NULL, 'r'}, @@ -1106,6 +1111,31 @@ : memcmp ((char *) &a, (char *) &b, sizeof a)); } +static int +ipaddresscompare (const char *a, const char *b) +{ + struct in_addr ia; + struct in_addr ib; + + int is_a; + int is_b; + + while (blanks[to_uchar (*a)]) + a++; + while (blanks[to_uchar (*b)]) + b++; + + is_a = inet_pton (AF_INET, a, &ia); + is_b = inet_pton (AF_INET, b, &ib); + if (is_a > 0 && is_b > 0) + { + uint32_t sa = ntohl (ia.s_addr); + uint32_t sb = ntohl (ib.s_addr); + return sa == sb ? 0 : sa < sb ? -1 : 1; + } + return is_a > 0 ? -1 : is_b > 0 ? 1 : 0; +} + /* Return an integer in 1..12 of the month name MONTH with length LEN. Return 0 if the name in S is not recognized. */ @@ -1192,6 +1222,14 @@ diff = getmonth (texta, lena) - getmonth (textb, lenb); /* Sorting like this may become slow, so in a simple locale the user can select a faster sort that is similar to ascii sort. */ + else if (key->ipaddress) + { + char savea = *lima, saveb = *limb; + + *lima = *limb = '\0'; + diff = ipaddresscompare (texta, textb); + *lima = savea, *limb = saveb; + } else if (hard_LC_COLLATE) { if (ignore || translate) @@ -2078,6 +2116,9 @@ case 'M': key->month = true; break; + case 'I': + key->ipaddress = true; + break; case 'n': key->numeric = true; break; @@ -2187,7 +2228,7 @@ gkey.sword = gkey.eword = SIZE_MAX; gkey.ignore = NULL; gkey.translate = NULL; - gkey.numeric = gkey.general_numeric = gkey.month = gkey.reverse = false; + gkey.numeric = gkey.general_numeric = gkey.month = gkey.ipaddress = gkey.reverse = false; gkey.skipsblanks = gkey.skipeblanks = false; files = xnmalloc (argc, sizeof *files); @@ -2263,6 +2304,7 @@ case 'g': case 'i': case 'M': + case 'I': case 'n': case 'r': { @@ -2419,7 +2461,7 @@ for (key = keylist; key; key = key->next) if (! (key->ignore || key->translate || (key->skipsblanks | key->reverse - | key->skipeblanks | key->month | key->numeric + | key->skipeblanks | key->month | key->ipaddress | key->numeric | key->general_numeric))) { key->ignore = gkey.ignore; @@ -2427,13 +2469,14 @@ key->skipsblanks = gkey.skipsblanks; key->skipeblanks = gkey.skipeblanks; key->month = gkey.month; + key->ipaddress = gkey.ipaddress; key->numeric = gkey.numeric; key->general_numeric = gkey.general_numeric; key->reverse = gkey.reverse; } if (!keylist && (gkey.ignore || gkey.translate - || (gkey.skipsblanks | gkey.skipeblanks | gkey.month + || (gkey.skipsblanks | gkey.skipeblanks | gkey.month | gkey.ipaddress | gkey.numeric | gkey.general_numeric))) insertkey (&gkey); reverse = gkey.reverse; _______________________________________________ Bug-coreutils mailing list Bug-coreutils@gnu.org http://lists.gnu.org/mailman/listinfo/bug-coreutils