Когда их попросят сопоставить IP-адрес, многие напишут
/\d+\.\d+\.\d+\.\d+/
, но это даст ложные срабатывания.В Джеффри Фридла "Освоение регулярных выражений" автор дает образец для сопоставления IP-адресов, который гораздо более осторожен.Приведенный ниже код заимствован у Фридла, чтобы вызвать не произвольный набор цифр, а в диапазоне от 0 до 255, требует, чтобы адрес начинался и заканчивался на границах слова (\b
), и запрещал адрес 0.0.0.0.
Без аргументов приведенный ниже код по умолчанию соответствует текущему каталогу для начала его поиска.Для поиска по всем файлам укажите корневой каталог в качестве аргумента.Открывая каждый путь, который выводит find
, мы затем ищем в каждой строке IP-адрес и печатаем все совпадения вместе с соответствующими путями.
Обратите внимание, как код использует local
для прозрачного переключения между символом NUL и символом новой строки для разделителя записей $/
.Это необходимо, потому что действие find
-print0
разделяет имена файлов с помощью '\0'
, но '\n'
является разделителем строки.С -T
мы ищем только текстовые файлы.
#! /usr/bin/perl
use warnings;
no warnings 'exec';
use strict;
my $octet = qr/[01]?\d\d?|2[0-4]\d|25[0-5]/;
my $ip = qr/ \b
(?!0+\.0+\.0+\.0+\b)
$octet(?:\.$octet){3}
\b
/x;
@ARGV = (".") unless @ARGV;
open my $find, "-|", "find", @ARGV, "-type", "f", "-print0"
or die "$0: failed to start find: $!\n";
$/ = "\0";
while (defined(my $path = <$find>)) {
chomp $path;
next unless -T $path;
if (open my $fh, "<", $path) {
local $/ = "\n";
while (<$fh>) {
print "$path: $_" if /$ip/;
}
close $fh;
}
else {
warn "$0: open $path: $!\n";
}
}