Сортировка IP-адресов в vim - PullRequest
5 голосов
/ 30 января 2012

Я только что обнаружил команду :sort n в vim (как я не знал об этом ?!), которая почти сделала именно то, что мне нужно.

Однако я пытаюсь отсортировать длинный список IP-адресов (это файл "allow hosts", который в нашей конфигурации apache должен быть Include d), и было бы неплохо, чтобы :sort n был в состоянии распознать, что 123.45.6.7 должен сортироваться до 123.45.16.7 (например).

Это безопасное предположение, что я должен быть менее ОКР по этому поводу и не беспокоиться, потому что я не смогу сделать это без слегка сложной sed или awk команды или чего-то еще? *

Для ясности, все строки выглядят примерно так:

Allow from 1.2.3.4
Allow from 5.6.7.8
Allow from 9.10.11.12

и т.д.

Ответы [ 3 ]

10 голосов
/ 30 января 2012

Vim сортировка кажется стабильной на практике (но это не гарантируется). Поэтому вы можете попробовать:

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

, который будет сортировать по номеру после последней точки (* является жадным), затем по номеру после первой точки, следующей за точкой и цифрами, затем по номеру после первой точки и последним по первой цифре.

3 голосов
/ 31 января 2012

Существует надежный способ добиться правильной сортировки: добавьте нули к номерам адресов, чтобы все они состояли из трех цифр.

  1. Предварительно добавьте нули к числам.

    :%s/\<\d\d\?\>/0&/g|%&&
    
  2. Сортировка строк, сравнивающих IP-адреса, как текст.

    :sort r/\(\d\{3}\)\%(\.\d\{3}\)\{3}/
    
  3. Удаление лишних начальных нулей.

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

Чтобы выполнить все три шага одной командой, используйте однострочник

:%s/\<\d\d\?\>/0&/g|%&&|sor r/\(\d\{3}\)\%(\.\d\{3}\)\{3}/|%s/\<00\?\ze\d//g
0 голосов
/ 30 января 2012

Я не являюсь пользователем vim, поэтому я не могу предложить прямой способ сделать это с помощью встроенных команд, однако можно заменить часть текста на вывод, который выполняется через команду.Таким образом, можно использовать простой скрипт, подобный этому:

#!/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)

См. https://www.linux.com/learn/tutorials/442419-vim-tips-working-with-external-commands, раздел «Фильтрация текста через внешние фильтры», который объясняет, как вы можете использовать его в качестве фильтра в vim.

Этот скрипт должен делать то, что вы хотите, и будет работать в любом регионе, где все выделенные строки заканчиваются адресом IPv4.

...