in reply to Variable initialization / reinitialization

This reminds me a bit of what finally pushed me over the edge from bash to Perl many years ago - validating and sorting lists of IP addresses. In hindsight, I bet there's a module for the task, but it was a good exercise. Anyhow, borrowing from that years-old effort:

use strict; use warnings; while(<DATA>){ chomp; my $mask = (split(/\s+/, $_))[2]; print "Mask $mask is ", &Valid($mask), "\n"; } sub Valid { my @octs; local $_ = shift; return 0 if !defined $_; return 0 if m{(?:(?:^|\.)[^0]\d*\.)(?!255)}; return 0 if (@octs = split(/\./, $_)) ne 4; return 0 if grep {!m/^(?:0|3|7|15|31|63|127|255)$/} @octs; return 1; } __DATA__ field1 10.1.253.11 0.0.0.0 field1 10.1.254.0 0.0.0.64 field1 10.1.254.128 0.0.0.63 field1 10.1.158.0 15.255.0.255 field1 10.1.160.0 0.0.0.37 field1 10.1.161.0 0.0.146.255 field1 10.1.161.0 0.0.255 field1 10.1.161.0 0.0.255.255 field1 10.1.161.0 255.0.0.0 field1 10.1.158.0 15.255.255.127

I'm not sure I followed your non-zero/non-255 rule. I interpreted it as, once there's a non-zero octet, all thereafter must be 255.

Replies are listed 'Best First'.
Re^2: Variable initialization / reinitialization
by BTrey (Novice) on Feb 09, 2009 at 21:52 UTC
    Just wanted to thank you for your comment. It made a light go on in my head. The code is intended to validate an inverse mask. That's the inverse of a subnet mask - it masks off the network portion and keeps the host portion of an IP. In binary, that means it's 0 or more zeros followed by the rest of the string being all 1s. So, in dotted decimal format, you'll get 0 or more 0 octets, followed by 1 non-zero octet that is 1 less than a power of 2, followed by octets that are 255. But the binary representation is actually much easier to check for! So, with some help from The Perl Cookbook (for the pack/unpack cycle to convert a number to its binary string):
    sub ValidateMasks() { my $mask = shift; return 0 if !defined $mask; my $binary_rep; my @octets = split (/\./, $mask); for my $octet (@octets) { $binary_rep .= substr(unpack("B32", pack("N", $octet)), -8); } return $binary_rep =~ /^0*1*$/; }