Search code examples
csortingunixfunction-prototypes

Unixy way of sorting C prototypes alphabetically


Suppose you have a list of C function prototypes, one per line, like

void   foo(void);
struct baz *zap(void (*callback)(void));
long long blurb(long i);
long double sinus(long double arg);
sometype_t somefunc(void);

Sorted by function name the result is

long long blurb(long i);
void   foo(void);
long double sinus(long double arg);
sometype_t somefunc(void);
struct baz *zap(void (*callback)(void));

As far as I read the sort(1) manual, this cannot be sorted using -k options, since the function identifier is sometimes the second word, sometimes the third (lets ignore cases where the function identifier is even further to the right, as when structs are spelled out).

But I know that the function identifier is the string before the first '(' token on the line. Does anyone know a unixy way to sort this? Unixy := a one line filter/pipe. I could probably hack up an ugly perl solution deleting the uninteresting left part, sorting, and restoring the left part, but that's nowhere near a one-liner.


Solution

  • But I know that the function identifier is the string before the first '(' token on the line

    The usual way I go about such sorting tasks, is to use sed with a good regex to insert a unique separator into the input, that I can later use with sort. After sorting the separator can be removed. So:

    1. Insert ( in front of the function identifier.
    2. Sort by second column using ( as separator.
    3. Remove the first ( from the line.

    The following:

    sed 's/\([a-zA-Z0-9_]*(\)/(\1/' | sort -t'(' -k2 | sed 's/(//'
    

    with the following input:

    void   foo(void);
    struct baz *zap(void (*callback)(void));
    long long blurb(long i);
    long double sinus(long double arg);
    sometype_t somefunc(void);
    

    outputs on repl:

    long long blurb(long i);
    void   foo(void);
    long double sinus(long double arg);
    sometype_t somefunc(void);
    struct baz *zap(void (*callback)(void));