
У меня есть файл со списком 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