perl +不规则表达式(VALID IP + ADD有效规则)

时间:2010-09-07 18:51:33

标签: perl

以下语法是带有Irregular Expression的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 个答案:

答案 0 :(得分:2)

你有两个问题:

  1. 需要在八位字节定义中添加“*”。

  2. 更糟糕的是 - “*”匹配字边界(\ w)。所以你应该使用ip-boundary的显式字符类:[^\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";
    }
    
  3. 输出:

    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 :(得分:1)

你为什么需要这样做?你应该使用适当的CIDR表示法,例如124.33 / 16,然后您可以使用标准的Net :: IP :: *模块来处理IP范围。

答案 2 :(得分:1)

#!/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";
    }
}

答案 3 :(得分:0)

它们被称为正则表达式(不是不规则表达式)。

如果你想要一个特定的前缀,你可以说

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

答案 4 :(得分:0)

这应该是显而易见的,但是子类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在1-255(8位)的范围内,就可以显示为{a,b,c,d}。这意味着,询问*.1.2.3,代表1.2.3.42.2.3.4,而不是1.2.3.5没有任何技术价值。没有理由需要这个。但你可以用快速的二进制算法来完成它。