Sort input file by the results of a regex

A general method to sort by an arbitrary function of the contents of the line is as follows:

  1. Get the key you want to sort by, and copy it to the beginning of the line
  2. Sort
  3. Delete the key from the beginning of the line

Here is a key you can use in this particular case: this sed program will output the the line from the last identifier to the end.

% sed -e 's/^.*[^[:alnum:]_]\([[:alpha:]][[:alnum:]_]*\)/\1/' < decls

albumArtView; // 1
profileView;  // 2
postFB;          // 3
saveButton;      // 4

To put these keys and the original lines side by side:

% paste <(sed -e 's/^.*[^[:alnum:]_]\([[:alpha:]][[:alnum:]_]*\)/\1/' < decls) decls

To sort them ...

| sort

and to leave just the second field (the original line)

| cut -f 2-

All together (sorting in reverse order, so there's something to show):

% paste <(sed -e 's/^.*[^[:alnum:]_]\([[:alpha:]][[:alnum:]_]*\)/\1/' < decls) decls \
  | sort -r \
  | cut -f 2-

@property (nonatomic, assign) UIButton *saveButton;      // 4
@property (nonatomic, strong, readonly) UIImageView *profileView;  // 2
@property (nonatomic, strong, readwrite) UIButton *postFB;          // 3
@property (nonatomic, strong) id <AlbumArtDelegate, UITextFieldDelegate> *albumArtView; // 1

PIPED-DATA | sed -r "s/(\*\w+)/\x01&\x01/" | sort -k2 -t$'\x01' |tr -d $'\x01'

The above script is enough for your situation. Actually it is basically enough for any single-key-field sort.. For the same script, expanded, read on.


The following script sets up the field to be sorted as 2, but the field layout is quite flexible. You can sort on multiple fields, if you need to, by specifying appropriate regex patterns, and changing the sort options accordingly.

Each field pattern should be wrapped in normal (brackets) and 'single-quoted'.

The patterns which you provide are delimited by any unique character you choose. sed also needs a unique delimiter. The script uses delimiters \x01 and \x02. These delimiter values were chosen because they do not normallay appear in text files.

Note that your setup must be considered as being based on field composiiton, not by field delimiters..

n=2                                  # field number to sort on
p=( '(.*)'  '(\*\w+)'  '(.*)' )      # Set up regex field patterns

f=; r=; d=$'\x01';  x=$'\x02'        # Build patterns and delimiters
for (( i=0; i<${#p[@]}; i++ )) ;do 
   f+="${p[i]}"; r+="\\$((i+1))$x"
done

sed -r "s$d$f$d$r$d" file |sort -k$n -t"$x" |tr -d  "$x"

Output:

@property (nonatomic, strong) id <AlbumArtDelegate, UITextFieldDelegate> *albumArtView; // 1
@property (nonatomic, strong, readwrite) UIButton *postFB;          // 3
@property (nonatomic, strong, readonly) UIImageView *profileView;  // 2
@property (nonatomic, assign) UIButton *saveButton;      // 4