2012-01-30 20 views
5

Acabo de descubrir el comando :sort n en vim (¿cómo es que no lo sabía ?!), que tiene casi hecho exactamente lo que necesito.Ordenando direcciones IP en vim

Lo que estoy tratando de ordenar, sin embargo, es una larga lista de direcciones IP (es un archivo "permitir hosts" ser Include d en nuestra configuración de apache), y sería bueno para :sort n ser capaz de reconocer que 123.45.6.7 debe ordenar antes de 123.45.16.7 (por ejemplo).

¿Es una suposición segura que debería ser menos TOC al respecto y no preocuparme, porque no voy a poder hacer esto sin un comando ligeramente complejo sed o awk o algo así?

Para ser claros, las filas todos miran algo como:

Allow from 1.2.3.4 
Allow from 5.6.7.8 
Allow from 9.10.11.12 

etc

Respuesta

8

El tipo de Vim parece ser estable en la práctica (pero no está garantizado). Por lo tanto se puede probar:

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

que clasificará por número tras el último punto (* es codicioso), y luego por número después del primer punto después de un punto y dígitos, a continuación, por número después del primer punto, y por último por el primer número.

+0

Casi perfecto (y la única razón por la que no lo era porque no había mencionado que algunas de mis filas eran máscaras de red). Gracias; eso me llevó lo suficiente como para ordenar las máscaras de red yo mismo. –

+1

Usando la tubería puede ejecutarlo todo de una vez: ':% sort n /.*\./ | % sort n /\.\d\+\./ | % sort n /\./ | % ordenar n' – azzid

0

No soy un usuario vim así que no puedo ofrecer una forma directa de hacerlo con las órdenes internas, sin embargo, es posible reemplazar una sección de texto con la salida ejecutada a través de un comando. Por lo tanto, una secuencia de comandos simple como esto podría ser utilizado:

#!/usr/bin/python 

import sys 

input_lines = sys.stdin.readlines() 
sorted_lines = sorted(input_lines, 
         key=lambda line: map(int, line.split()[-1].split('.'))) 
for line in sorted_lines: 
    sys.stdout.write(line) 

Ver https://www.linux.com/learn/tutorials/442419-vim-tips-working-with-external-commands, sección "Filtrado de texto a través de filtros externos", que explica cómo se puede utilizar esto como un filtro dentro de vim.

Este script debe hacer lo que quiera y funcionará en cualquier región donde todas las líneas seleccionadas terminen en una dirección IPv4.

+0

Bondad, gracias. Estaba tratando de evitar ejecutar un script (principalmente porque es un servidor de Producción no vivo, así que tiene una instalación escueta y 'python' no está ahí), pero eso se ve increíble; ¡gracias! –

2

Existe una forma confiable de lograr la clasificación correcta: anteponer ceros a los números de dirección para que todos ellos tengan tres dígitos.

  1. Ponga los ceros a cero en los números.

    :%s/\<\d\d\?\>/0&/g|%&& 
    
  2. Ordene las líneas que comparan las direcciones IP como texto.

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

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

Para ejecutar los tres pasos como un comando, utilice el de una sola línea

:%s/\<\d\d\?\>/0&/g|%&&|sor r/\(\d\{3}\)\%(\.\d\{3}\)\{3}/|%s/\<00\?\ze\d//g 
Cuestiones relacionadas