Форматирование 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
остается в покое.