Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting IP addresses in vim

I have just discovered the command :sort n in vim (how did I not know about that?!), which has almost done exactly what I need.

What I am trying to sort, though, is a long list of IP addresses (it's an "allow hosts" file to be Included into our apache config), and it would be nice for :sort n to be able to recognise that 123.45.6.7 should sort before 123.45.16.7 (for example).

Is it a safe assumption that I should be less OCD about it and not worry, because I'm not going to be able to do this without a mildly-complex sed or awk command or something?

To be clear, the rows all look something like:

Allow from 1.2.3.4
Allow from 5.6.7.8
Allow from 9.10.11.12

etc

like image 886
Owen Blacker Avatar asked Jan 30 '12 16:01

Owen Blacker


2 Answers

Vim sort seems to be stable in practice (but it is not guaranteed). Therefore you can try:

:%sort n /.*\./
:%sort n /\.\d\+\./
:%sort n /\./
:%sort n

Which will sort by number after the last dot (* is greedy), then by number after the first dot following a dot and digits, then by number after the first dot, and last by the first number.

like image 58
Benoit Avatar answered Oct 22 '22 14:10

Benoit


A straightforward way to achieve the correct sorting order without relying on the stability of the sorting algorithm implemented by the :sort command, is to prepend zeroes to the numbers within the IP addresses, so that all of the components in them consist of exactly three digits.

  1. Prepend zeros to the single-digit and two-digit numbers:

    :%s/\<\d\d\?\>/0&/g|%&&
    
  2. Sort the lines comparing IP addresses as text:

    :sort r/\(\d\{3}\)\%(\.\d\{3}\)\{3}/
    
  3. Strip redundant leading zeros:

    :%s/\<00\?\ze\d//g
    

To run all three steps as a single command, one can use the following one-liner:

:%s/\<\d\d\?\>/0&/g|%&&|sor r/\(\d\{3}\)\%(\.\d\{3}\)\{3}/|%s/\<00\?\ze\d//g
like image 25
ib. Avatar answered Oct 22 '22 13:10

ib.