perl + неправильное выражение (VALID IP + ADD Valid Rule) - PullRequest
2 голосов
/ 07 сентября 2010

следующий синтаксис является частью сценария perl с нерегулярным выражением как мы видим, целью следующего синтаксиса является получение VALID IP-адреса как 123.33.44.5 или 255.255.0.0 и т. д.

но как изменить следующий синтаксис, если я хочу подтвердить также IP:

например:

  124.33.*.* 

(я хочу также указать символ * как действительное число 1-255)

пример действительных IP-адресов

*.1.23.4

123.2.*.*

*.*.*.*

*.*.198.20

пример недопустимых IP-адресов

 123.**.23.3

 289.2.2.2

 21.*.*.1000

" *.*.*.**"
#

мой исходный код:

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;

Ответы [ 5 ]

2 голосов
/ 07 сентября 2010

У вас 2 проблемы:

  1. Необходимо добавить «*» к определению октета.

  2. Гораздо хуже - "*" соответствует границе слова (\ w). Поэтому вместо ip-border вы должны использовать явный класс символов: [^\d*]

    my $octet = qr/[01]?\d\d?|2[0-4]\d|25[0-5]|[*]/; 
    my $ip = qr/\b0+\.0+\.0+\.0+\b|(?:[^\d*]|^)$octet(?:[.]$octet){3}([^\d*]|$)/x;
    
    foreach $str (@ip_list) { 
        print "$str - ";
        print "NO " if $str !~ $ip;
        print "match\n";
    }
    

ВЫВОД:

1.1.1.1 - match
123.1.*.* - match
1.*.3.4 - match
*.192.2.2 - match
23.*.3.3 - match
*.1.23.4 - match
123.2.*.* - match
*.*.*.* - match
*.*.198.20 - match

123.**.23.3 - NO match
289.2.2.2 - NO match
21.*.*.1000 - NO match
*.*.*.** - NO match

11.12.13.14 - match
1.*.3.4 - match
1.*.3.* - match
0.00.0.0 - match
1 голос
/ 08 сентября 2010
#!/usr/bin/perl

use strict;
use warnings;

sub is_ip_with_wildcards {
    my ($ip) = @_;
    my @octets = split / [.] /xms, $ip;    
    return 4 == grep { $_ eq q{*} || m/ \A [0-9]+ \z /xms && $_ < 256 } @octets;
}

while( defined( my $line = <> ) ) {
    if( my @ips = grep { is_ip_with_wildcard( $_ ) } split q{ }, $line ) {
        print 'found IPs: ', join(q{, }, @ips), "\n";
    }
}
1 голос
/ 07 сентября 2010

Зачем вам это нужно?вместо этого вы должны использовать правильную нотацию CIDR, например 124.33 / 16, а затем вы можете использовать стандартные модули Net :: IP :: * для обработки диапазонов IP-адресов.

0 голосов
/ 08 сентября 2010

Это должно быть очевидно, но подкласс Net::IP. Здесь я делю его на SillyIP и обертываю функцию set. В реальной жизни я бы, вероятно, подкласс это Net::IP::SillyIP.

package SillyIP;
use Moose;

extends 'Net::IP';

around 'set' => sub {
  my ( $orig , $self, $ip, @args ) = @_;

  die "invalid IP" if $ip =~ /\*{2}|\s/;

  if ( $ip =~ /\.\*/ ) {
    my $count = ( $ip =~ s/(\.\*)+$/.0/g );
    $ip .= '/' . (abs(4- $count)*8);
  }

  $self->$orig( $ip, @args );

};

1;

package main;

use Test::More tests => 5;

eval { SillyIP->new('10.**.1.1') };
ok ( $@, 'Fail to accept **' );

eval { SillyIP->new(' 10.0.1.1 ') };
ok ( $@, 'Fail to accept spaces in ip' );

is ( SillyIP->new('10.*.*.*')->ip, SillyIP->new('10/8')->ip, '8 bit network' );
is ( SillyIP->new('192.168.*.*')->ip, SillyIP->new('192.168/16')->ip, '16 bit network' );
is ( SillyIP->new('192.168.1.*')->ip, SillyIP->new('192.168.1/24')->ip, '24 bit network' );

Это обеспечит 90% того, что вы просите. Однако он не принимает * в качестве диапазона для цифры. Это потому, что IPv4-адреса не являются десятичными. На самом деле это просто 32-битные структуры данных, которые могут отображаться как a.b.c.d, если {a,b,c,d} находится в диапазоне 1-255 (8 бит). Это означает, что запрос *.1.2.3 для представления 1.2.3.4 и 2.2.3.4, но не 1.2.3.5 не имеет никаких технических достоинств. Нет причин когда-либо нуждаться в этом. Но вы могли бы сделать это с помощью быстрого двоичного алгоритма.

0 голосов
/ 07 сентября 2010

Они называются регулярными выражениями (не неправильными выражениями).

Если вам нужен конкретный префикс, вы можете просто сказать

my $octet = qr/[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-5]/
my $ip = qr/\b124[.]33[.]$octet[.]$octet\b/;

Предупреждение о вашем регулярном выражении, хотя с Perl 5.8 \d больше не соответствует просто [0-9]. Вместо этого он совпадает с символом Unicode, поэтому строка "①.①.①.①" будет соответствовать как "᠐.᠐.᠐.᠐" (что еще хуже, поскольку в монгольском это 0.0.0.0). Всегда используйте [0-9] вместо \d, если вы не хотите таких совпадений.

Это то, что вы ищете?

#!/usr/bin/perl

use strict;
use warnings;

sub wildcard_to_regex {
    my $wildcard = shift;
    my @octets   = split /[.]/, $wildcard;

    for my $octet (@octets) {
        next unless $octet eq "*";
        $octet = qr/[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]/;
    }

    my $regex = '\b' . join("[.]", @octets) . '\b';
    return qr/$regex/;
}

for my $wildcard (qw/8.8.8.8 *.*.*.0 1.1.1.* 1.1.*.1/) {
    my $regex = wildcard_to_regex($wildcard);

    print "$wildcard\n";
    for my $test (qw/1.1.1.0 1.1.1.1 1.1.2.1/) {
        print "\t$test ",
            $test =~ $regex ? "matched" : "didn't match", "\n";
    }
}

печатает

8.8.8.8
        1.1.1.0 didn't match
        1.1.1.1 didn't match
        1.1.2.1 didn't match
*.*.*.0
        1.1.1.0 matched
        1.1.1.1 didn't match
        1.1.2.1 didn't match
1.1.1.*
        1.1.1.0 didn't match
        1.1.1.1 matched
        1.1.2.1 didn't match
1.1.*.1
        1.1.1.0 didn't match
        1.1.1.1 matched
        1.1.2.1 matched
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...