Форматирование IP с помощью sed

Я пытаюсь выяснить, как сделать следующее с sed:

У меня есть список адресов IPv4, и я пытаюсь сделать их одинаковыми на дисплее. Так, например: 1.2.4.32 будет 001.002.004.032. 10.125.62.1 будет 010.125.062.001.

Я пытаюсь использовать sed, чтобы сделать это, потому что это то, что я изучаю прямо сейчас.

Я получил эти два, которые возьмут любое одно или два цифры и добавят нули спереди.

sed 's/\<[0-9][0-9]\>/0&/g' file
sed 's/\<[0-9]\>/00&/g' file

Но это сталкивается с более практичной проблемой, так как мой входной файл будет иметь номера с одним или двумя цифрами в других местах, отличных от IP-адреса. Пример:

host-1 1.2.3.32

Итак, мне нужен способ поиска полного IP-адреса, который, как я думал, может быть достигнут с помощью этого

sed 's/\.\<[0-9]\>/00&/g'

но не только это игнорирует случай 1.something.something.something, но также по какой-то причине добавляет 00 в конце 3-го октета.

echo "10.10.88.5" | sed 's/\.\<[0-9]\>/00&/g'
10.10.8800.5

Пример файла:

Jumpstart Server jumo     10.20.5.126
Jumpstart Server acob     10.20.5.168
NW1 H17  Node cluster     10.10.161.87
NW1 H17  Node-1       10.10.161.8
NW1 H17  Node-2       10.10.161.9
ts-nw1      10.10.8.6

Ответ 1

$ cat 37222835.txt
Jumpstart Server jumo     10.20.5.126 10.29.23.24
Jumpstart Server acob     10.20.5.168 dig opt
Jumpstart Server reac     251.218.212.1 rel
NW1 H17  Node cluster     10.10.161.87
NW1 H17  Node-1       10.10.161.8
NW1 H17  Node-2       10.10.161.9
ts-nw1      10.10.8.6
Nw2 HW12 Node-3       192.168.0.1
cluster

Выполнение:

sed -n 's/\([1]\?[0-9][0-9]\?\|2[0-4][0-9]\|25[0-5]\)\{1\}\.'\
'\([1]\?[0-9][0-9]\?\|2[0-4][0-9]\|25[0-5]\)\{1\}\.'\
'\([1]\?[0-9][0-9]\?\|2[0-4][0-9]\|25[0-5]\)\{1\}\.'\
'\([1]\?[0-9][0-9]\?\|2[0-4][0-9]\|25[0-5] \)/00\1\.00\2\.00\3\.00\4/g;
s/0\+\([0-9]\{3\}\)/\1/g;p' 37222835.txt

дает:

Jumpstart Server jumo     010.020.005.126 010.029.023.024
Jumpstart Server acob     010.020.005.168 dig opt
Jumpstart Server reac     251.218.212.001 rel
NW1 H17  Node cluster     010.010.161.087
NW1 H17  Node-1       010.010.161.008
NW1 H17  Node-2       010.010.161.009
ts-nw1      010.010.008.006
Nw2 HW12 Node-3       192.168.000.001
cluster

Преимущество подхода, упомянутого в статье @benjamin-w

Это может заменить несколько IP-адресов в одной строке

Недостаток (подход, упомянутый @benjamin-w, исправляет это)

Если бы было слово say Node-000234, оно было бы изменено на Node-234. Фактически, вы можете работать с второй командой подстановки, чтобы получить желаемое поведение.

Ответ 2

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

Это должно работать (замените -r на -E для BSD sed):

sed -r 'h                  # Copy pattern space to hold space

# Remove everything except IP address from pattern space
s/.*\b(([0-9]{1,3}\.){3}[0-9]{1,3})\b.*/\1/

s/([0-9])+/00&/g           # Prepend '00' to each group of digits
s/[0-9]*([0-9]{3})/\1/g    # Only retain last three digits of each group
G                          # Append hold space to pattern space

# Replace old IP with new IP
s/(.*)\n(.*)\b([0-9]{1,3}\.){3}[0-9]{1,3}\b(.*)/\2\1\4/' infile

Последний шаг - самый сложный. Прямо перед этим строка выглядит так (новая строка как \n, конец строки как $):

010.020.005.126\nJumpstart Server jumo     10.20.5.126$

т.е. наш новый и улучшенный IP-адрес, новая строка, а затем полная старая строка. Теперь мы фиксируем выделенные группы:

010.020.005.126\nJumpstart Server jumo     10.20.5.126$
^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^^^^^^^^^           ^
      (.*)     \n          (.*)              \b...\b  (.*)
       \1                   \2                  \3     \4

и перестройте линию, используя группу 2, затем группы 1 (наш новый IP) и 4. Обратите внимание, что

  • Есть четыре группы захвата, но третья только что помогает описать IP-адрес, мы фактически не хотим его сохранять, поэтому \2\1\4 в подстановке (в группе нет неперехваченных групп).
  • Последняя группа захвата (после IP-адреса) пуста, но с ее помощью она может использоваться для строк, которые имеют IP-адрес в любом месте.
  • Это заменяет только первый IP-адрес в каждой строке, если их несколько.

Общий вывод

Jumpstart Server jumo     010.020.005.126
Jumpstart Server acob     010.020.005.168
NW1 H17  Node cluster     010.010.161.087
NW1 H17  Node-1       010.010.161.008
NW1 H17  Node-2       010.010.161.009
ts-nw1      010.010.008.006

То же самое, что и сплошной нечитабельный однострочный:

sed -r 'h;s/.*\b(([0-9]{1,3}\.){3}[0-9]{1,3})\b.*/\1/;s/([0-9])+/00&/g;s/[0-9]*([0-9]{3})/\1/g;G;s/(.*)\n(.*)\b([0-9]{1,3}\.){3}[0-9]{1,3}\b(.*)/\2\1\4/' infile

\b является расширением GNU. script в основном работает без него; используя его, убедитесь, что blah1.2.3.4blah остается в покое.