Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Need help with a nested IF statement

by MikeDexter (Sexton)
on Nov 02, 2009 at 15:25 UTC ( [id://804470]=perlquestion: print w/replies, xml ) Need Help??

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

I am writing a Perl script that will run on Solaris an "ifconfig" then will print out the name of the device and the ip address for that device. I have two IF statements that work on their own but when I place them both into my foreach loop, the second IF gets skipped over. I entered a print "test" line to debug and the word test never appears in the output. I have these in the same foreach so that they align the IP address and device together.

My expected output would be "Device 0 has an ip address of xxx.xxx.xxx.xxx newline Device 1 has an ip address of xxx.xxx.xxx.xxx newline exit-loop.

$ifconfig = "ifconfig -a"; @nic = qx |$ifconfig| or die ("Can't get info from ifconfig: ".$!); foreach (@nic){ if (/^fjgi([\d.])/){ $device = $1; if (/inet ([\d.]+)/){ print "test $1\n"; $ip = $1; } print "Device $device has the IP Address of $ip\n"; } }

Replies are listed 'Best First'.
Re: Need help with a nested IF statement
by ikegami (Patriarch) on Nov 02, 2009 at 15:44 UTC

    Why are you printing the IP address when you have haven't found one (i.e. when the inner if hasn't been entered)? Don'thide errors. Please use use strict; use warnings;!

    use strict; use warnings; my $ifconfig = "ifconfig -a"; my @nic = qx |$ifconfig| or die("Can't get info from ifconfig: $!\n"); for (@nic){ if (my ($device) = /^fjgi(\d)/){ if (my ($ip) = /inet ([\d.]+)/){ print "Device $device has the IP Address of $ip\n"; } } }

    I have two IF statements that work on their own but when I place them both into my foreach loop, the second IF gets skipped over

    Are you sure there's a line that both starts with fjgi and contains inet? I'm not familiar with the output of ifconfig, but I suspect that isn't the case.

      Hi there. I tried changing my IF's to resemble your example but when I run the script I don't get any output. This script from the top will first identify the operating system and then dump into the appropriate loop per the os it finds. For Solaris, $opsys is not true for linux so we jump to the else statement. There is the code as per your suggestion. When I run the script on Solaris is says I am on Solaris but no other data is printed at all.

      Would you mind taking another look to see if I missed something?

      use strict; use warnings; my($opsys) = "$^O"; print "Hello, your operating system is: $opsys" . "\n"; if ($opsys =~ /linux/) { my $ifconfig = "/sbin/ifconfig"; my @nic = qx |$ifconfig| or die ("Can't get info from ifconfig: $!\ +n"); for(@nic){ if (my ($device) = /eth(\d)/){ if (my ($ip) = /net addr:([\d.]+)/){ print "Device $device has the IP Address of $ip\n"; } } } } else { my $ifconfig = "ifconfig -a"; my @nic = qx |$ifconfig| or die ("Can't get info from ifconfig: $!\ +n"); for (@nic){ if (my ($device) = /^fjgi(\d)/){ if (my ($ip) = /inet ([\d.]+)/){ print "Device $device has the IP Address of $ip\n"; } } } }

        I tried changing my IF's to resemble your example but when I run the script I don't get any output.

        Of course. You haven't fixed the problem of the inner "if" not matching

        Would you mind taking another look to see if I missed something?

        You seem to have missed the question in my earlier post. ( I see you addressed that in a separate post. Replying to that post now )

      the ifconfig -a prints the following. The device name and ip are NOT on the same line. I don't know how to say look for x on line 1 and tell me y on line 2 after the second regex find..... Can I do that in Perl?

      output of command

      cccadm@redsox::perl: ifconfig -a lo0: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu +8232 index 1 inet 127.0.0.1 netmask ff000000 fjgi0: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 ind +ex 2 inet 10.254.190.232 netmask ffffff00 broadcast 10.254.190.255 fjgi1: flags=1000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4> mtu 1500 ind +ex 3 inet 10.254.140.221 netmask ffffff00 broadcast 10.254.140.255

        The device name and ip are NOT on the same line.

        Since you process each line one at a time, that's a problem.

        The easiest solution is to look at entire records.

        use strict; use warnings; my $opsys = $^O; print "Hello, your operating system is: $opsys\n"; if ($opsys =~ /linux/) { my $nics = qx|/sbin/ifconfig| or die("Can't get info from ifconfig: $!\n"); my @nics = split /(?<=\n)(?=\w)/, $nics; for (@nics){ my ($device) = /^eth(\d)/ or next; my ($ip) = /\bnet addr:([\d.]+)/ or next; print "Device $device has the IP Address of $ip\n"; } } else { my $nics = qx|ifconfig -a| or die("Can't get info from ifconfig: $!\n"); my @nics = split /(?<=\n)(?=\w)/, $nics; for (@nics){ my ($device) = /^fjgi(\d)/ or next; my ($ip) = /\binet ([\d.]+)/ or next; print "Device $device has the IP Address of $ip\n"; } }

        There's some redundancy here, but I can't figure how to eliminate cleanly.

Re: Need help with a nested IF statement
by SuicideJunkie (Vicar) on Nov 02, 2009 at 15:43 UTC

    Are you sure you want exactly 'fjgi' (case sensitive) at the beginning of the string with no optional whitespace between that and the capture?

    Most Importantly: You should print Dumper @nic; to ensure that you're working with what you think you're working with. Did you assume the system would split on '\n' for you?

Re: Need help with a nested IF statement
by toolic (Bishop) on Nov 02, 2009 at 15:46 UTC
    Add another print before your 2nd if:
    print ">>>$_<<<\n";
    That should prove to you that $_ has what you expect it to have.
Re: Need help with a nested IF statement
by keszler (Priest) on Nov 02, 2009 at 15:52 UTC
    I'm assuming that /^fjgi([\d.])/ matches and that you want the digits and/or '.'s that follow it to be $device.

    In my experience 'inet' appears on the line following the interface name, not on the same line as your example appears to assume. If this is the case, the following may be closer to what you want.

    use strict; my @nic = qx |ifconfig -a| or die ("Can't get info from ifconfig: ".$! +); my $skip_to_next_if = 0; my $device; foreach (@nic){ if (/^fjgi([\d.]+)/){ # ^ +: 1 or more $device = $1; $skip_to_next_if = 0; } next if $skip_to_next_if; if (/inet ([\d.]+)/){ my $ip = $1; print "Device $device has the IP Address of $ip\n"; $skip_to_next_if = 1; } } # $ip is now out of scope...
Re: Need help with a nested IF statement
by leocharre (Priest) on Nov 02, 2009 at 16:11 UTC
    yo yo yo.. what's up with the indentation.. I'm just being bold about what others have stated indirectly.. It's not
    if (..){ ... }
    It's
    if (..){ ... }
    This is important. So you won't drive yourself insane looking through your own code. Consider Perl Best Practices by Damian Conway. It's a tedious book, and you don't have to eat all of it. But there's some real useful stuff in there about consistency and why.
      Indenting the lines containing the { and } is very strange, but at least it is consistent.
      perltidy -pbp 804470
      $ifconfig = "ifconfig -a"; @nic = qx |$ifconfig| or die( "Can't get info from ifconfig: " . $! ); foreach (@nic) { if (/^fjgi([\d.])/) { $device = $1; if (/inet ([\d.]+)/) { print "test $1\n"; $ip = $1; } print "Device $device has the IP Address of $ip\n"; } }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://804470]
Approved by rovf
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (6)
As of 2024-04-16 09:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found