Это должно быть очевидно, но подкласс 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
не имеет никаких технических достоинств. Нет причин когда-либо нуждаться в этом. Но вы могли бы сделать это с помощью быстрого двоичного алгоритма.