Как заменить строку, которая НЕ соответствует IP-адресу, на фиктивный IP-адрес?

Как заменить строку, которая НЕ соответствует IP-адресу, на фиктивный IP-адрес?

У меня есть файл со списком IP-адресов, но некоторые строки не являются IP-адресами, и я хочу заменить такие строки фиктивным IP-адресом.

Я использую это grepдля поиска IP; но не знаю, как заменить то, что не совпадает, на фиктивный IP-адрес. Я думаю, это можно сделать с помощью sed. Я пробовал несколько вещей, но ни одна из них не сработала.

cat file.txt | grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'

У меня есть это sedдля сопоставления IP-адресов в файле, но я понятия не имею, как заменить не IP-адреса на фиктивный IP.

sed -rn '/([0-9]{1,3}\.){3}[0-9]{1,3}/p' file.txt

Вход:

192.168.10.20
00 03
10.28.214.5
192.168.10.40
BF
192.168.10.50

Желаемый результат:

192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50

Спасибо!

решение1

Ваше регулярное выражение будет соответствовать вещам, которыенетАдреса IPv4, разделенные четырьмя точками, но внешне похожи на них (например 256.256.256.256, очень похожи на адрес IPv4, но таковым не являются).

Только для соответствиядействительныйДля адресов IPv4 необходимо использовать регулярное выражение, например:

(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)

или (без ?:модификаторов группы perlish, не захватывающей):

((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)

и это должно быть надлежащим образом закреплено, например , с помощью ^и на обоих концах, или и .$\b\<\>

Видеть:Поваренная книга регулярных выраженийЯн Гойвертс и Стивен Левитан, опубликовано O'Reilly Media, Inc.

например

$ sed -E '/^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/!s/.*/192.168.0.0/' file.txt 
192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50
$ perl -p -e 's/.*/192.168.0.0/ unless m/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/' file.txt 
192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50

Оба варианта изменяют всю входную строку на 192.168.0.0, если только строка не соответствует действительному адресу IPv4.

Лично я бы использовал PerlРегулярное выражение::Общеемодуль, представляющий собой большую коллекцию регулярных выражений для общих задач сопоставления с шаблонами, удобно доступных в хэше под названием %RE.

$ perl -MRegexp::Common -p -e 's/.*/192.168.0.0/ unless m/^$RE{net}{IPv4}$/' file.txt 
192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50

решение2

ПРИМЕЧАНИЕ: другие указали, что выбранное вами регулярное выражение для адреса IPv4 имеет изъяны. Я не буду пытаться решать этот вопрос здесь, поскольку он хорошо освещен в другом месте.

Вы можете использовать sedсизмените команду на строки, которые не ( !) соответствуют вашему регулярному выражению, например.

$ sed -r '/([0-9]{1,3}\.){3}[0-9]{1,3}/!c\
192.168.0.0
' file.txt
192.168.10.20
192.168.0.0
10.28.214.5
192.168.10.40
192.168.0.0
192.168.10.50

С помощью GNU sed вы можете упростить

sed -r '/([0-9]{1,3}\.){3}[0-9]{1,3}/!c192.168.0.0' file.txt

решение3

sed '/^\([[:digit:]]\{1,3\}\.\)\{3\}[[:digit:]]\{1,3\}$/!s/.*/192.168.0.0/' data

Если строка не является допустимым адресом IPv4, замените текущую строку на: 192.168.0.0.

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

Или то же самое, но с awk:

awk '!/^([0-9]{1,3}\.){3}[0-9]{1,3}$/ {$0="192.168.0.0"}1' data

Или perl:

perl -MNet::IP -ple '$_ = "192.168.0.0" unless new Net::IP($_)' data

решение4

С Perl:

  • определить регулярное выражение октета, содержащего от одной до трех цифр с ограничением, что он не должен начинаться с нуля, если только он не состоит из одной цифры.
  • сопоставьте, что строка содержит ровно 4 октета, разделенных точками.
  • разбить линию на точки и убедиться, что все кортежи меньше 256.
dummy=192.168.0.0 \
perl -MList::Util=all -lpe '
  $octet //= qr/(?!0\d)\d{1,3}/;

  /^$octet(?:[.]$octet){3}$/ &&
   all { $_<256 } split /[.]/ or
     $_ = $ENV{dummy};
' file

Связанный контент