# Supports ranges in any number of bytes. sub parse_ip_mask { my ($ip_mask) = @_; my $checks = ''; my $check_num = 0; my $ip_re = join('\\.', map { if (/\[(\d+)-(\d+)\]/) { $check_num++; $checks .= " && \$$check_num >= $1"; $checks .= " && \$$check_num <= $2"; '(\\d+)' } else { $_ } } split(/\./, $ip_mask)); return eval "sub { (\$_[0] || \$_) =~ /^$ip_re\$/$checks }"; } my $ip_check = parse_ip_mask('131.202.1.[3-4]'); foreach (qw( 131.202.1.2 131.202.1.3 131.202.1.4 132.202.1.4 )) { print(&$ip_check() # Uses $_ if no arguments are specified. ? "$_ matches.$/" : "$_ doesn't match.$/" ); } __END__ output ====== 131.202.1.2 doesn't match. 131.202.1.3 matches. 131.202.1.4 matches. 132.202.1.4 doesn't match.