http://www.perlmonks.org?node_id=864126

sagarkha has asked for the wisdom of the Perl Monks concerning the following question:

Below is the subscript of my actual code, $fk is not getting the correct value it seems, though $MYIP1[0] is getting the desired IP.
open(F,'C:\Temp\ipconfig.txt') || die "error($!)"; while(<F>) { if(/IP Address/) { @split0= split(/ /, $_); @MYIP0=(@MYIP0,@split0); } if(/Gateway/) { @split1=split(/ /, $_); @MYGATEWAY0=(@MYGATEWAY0,@split1); } $i++; } foreach(@MYIP0) { if(/\b\d*\.\d*\.\d*\.\d*/) { @MYIP1=(@MYIP1, $_); } } foreach(@MYGATEWAY0) { if(/\b\d*\.\d*\.\d*\.\d*/) { @MYGATEWAY1=(@MYGATEWAY1, $_); } } my $ff="$MYIP1[0]"; my $fk="$ff:255.255.255.0"; $block4 = new2 Net::Netmask($fk); print $block4->size();
however when i manually assign IP to $ff, it works
my $ff="10.6.10.5"; my $fk="$ff:255.255.255.0"; $block4 = new2 Net::Netmask($fk); print $block4->size();

Replies are listed 'Best First'.
Re: Net::Netmask not working with scalar variable
by jwkrahn (Abbot) on Oct 08, 2010 at 06:22 UTC
    @MYIP0=(@MYIP0,@split0);

    That is usually written as:

    push @MYIP0, @split0;

    And also:

    if(/IP Address/) { @split0= split(/ /, $_); @MYIP0=(@MYIP0,@split0); }

    Can be simplified to:

    if(/IP Address/) { push @MYIP0, split; }


    if(/\b\d*\.\d*\.\d*\.\d*/)

    Your pattern will match the string "..." or "9999.9999.9999.9999" which are not valid IP addresses.


      Thanks jwkrahn, for all these suggestion, i will try to use these methods in my future scripts, this will reduce the line code.
Re: Net::Netmask not working with scalar variable
by CountZero (Bishop) on Oct 08, 2010 at 08:39 UTC
    If you find the IP in $MYIP1[0] but not in $ff, then it tells us that there is probably something wrong with your regular expression /\b\d*\.\d*\.\d*\.\d*/ . Matching IPs can be more tricky than you think, so perhaps you should use Regexp::Common and Regexp::Common::net to make sure you are really correctly matching an IP-adress.

    We would really like to help you more but $fk is not getting the correct value is a bit vague and ambiguous as an error message: Aren't you getting anything at all in $ff or only parts of the IP or ...?

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: Net::Netmask not working with scalar variable
by aquarium (Curate) on Oct 08, 2010 at 04:59 UTC
    it's a good idea to open a file for read only, if you only ever intend to only read the file, otherwise it gets opened automatically read+write.
    can't test your code at moment but generally when constructing funky strings, especially that $fk is input to a module/function, i'd recommend forming it like so
    my $fk = "$ff" . ':255.255.255.0';
    to make sure perl doesn't think that $ff: (for instance) is an entry into the symbol table instead of what you intend.
    so i always double quote variables separately, and attach other bits of strings in single quotes.
    the hardest line to type correctly is: stty erase ^H

      open is read only when mode is omitted. The 3 argument form of open is considered better practice:

      open(my $fh, '<', "input.txt") or die $!

      There is no reason to place a variable in double quotes unless you're interpolating it into a string, so the original poster's code was perfectly fine. To affect the symbol table you'd place 2 colons between barewords; like when you use a module or declare a package.

      I tried using my $fk = "$ff" . ':255.255.255.0';. I also tried using chomp; But no help in both the cases. I know my regex will matches more than just the Ip addresses like 2223.9991.55654.11111, but i damn sure it will match each and every IP address on the planet. And it is doing it correctly since i am getting the correct IP in $ff. Now, for more troubleshooting i tried printing $ff & $fk and i got the below results, i am not sure what is wrong here
      print "$ff\n"; print "$fk\n"; $block4 = Net::Netmask->new2($fk);
      Results:
      10.6.10.5 :255.255.255.0 Can't call method "size" on an undefined value at save.txt line 55, <F +> line 23.
Re: Net::Netmask not working with scalar variable
by ig (Vicar) on Oct 08, 2010 at 09:09 UTC

    You don't show the contents of your input file, but I am guessing something like:

    IP Address 1.2.3.4 Gateway 1.2.3.1

    When you read a line from your input file into $_, it includes the line termination character ("\n"). If there is no space character after the IP address in your configuration file, then you will end up with $ff set to something like "10.6.10.5\n" and $fk set to something like "10.6.10.5\n:255.255.255.0", when what you need is "10.6.10.5:255.255.255.0".

    There are several ways to deal with this, but one good one for you to learn is to use the chomp function to remove the line termination from your input. You could change your input loop to be like the following:

    while(<F>) { chomp; # Remove the "\n" from the end of the line # now use $_ }
Re: Net::Netmask not working with scalar variable
by Anonymous Monk on Oct 08, 2010 at 13:39 UTC
    while(<F>) { if(/IP Address/) { @split0= split(/ /, $_); @MYIP0=(@MYIP0,@split0); }
    Is almost certainly not what you want. If you do match /IP Address/ and then split on a space and then append to the list you will get something like:
    @MYIP0 = ( 'IP', 'Address', "192.168.1.1\r\n" )
    at best. Then even if you do match your /\d*\.\d*\.\d*\.\d*/ you're still keeping the wrong value. You probably want something like:
    while (<F> { if (/IP\sAddress\s+(\d+\.\d+\.\d+\.\d+)/) { push @MYIP, $1; } ... } $ff = $MYIP[0]; $fk = "$ff:255.255.255.0"; # even better, use 2 arg version of Net::Netmask->new2 $block = Net::Netmask->new2( $MYIP[0], '255.255.255.0'); ...
    The not perfect regex is OK since output from system commands rarely varies.