Stephen
Stephen

Reputation: 61

Perl comparison operation between a variable and an element of an array

I am having quite a bit of trouble with a Perl script I am writing. I want to compare an element of an array to a variable I have to see if they are true. For some reason I cannot seem to get the comparison operation to work correctly. It will either evaluate at true all the time (even when outputting both strings clearly shows they are not the same), or it will always be false and never evaluate (even if they are the same). I have found an example of just this kind of comparison operation on another website, but when I use it it doesn't work. Am I missing something? Is the variable type I take from the file not a string? (Can't be an integer as far as I can tell as it is an IP address).

$ipaddress = '192.43.2.130'
if ($address[0] == ' ')
{
open (FH, "serverips.txt") or die "Crossroads could not find a list of backend servers";
@address = <FH>;
close(FH);
print $address[0];
print $address[1];
}
for ($i = 0; $i < @address; $i++)
{
print "hello";
        if ($address[$i] eq $ipaddress)
        {print $address[$i];
        $file = "server_$i";
        print "I got here first";
        goto SENDING;}
}
SENDING:
print " I am here";

I am pretty weak in Perl, so forgive me for any rookie mistakes/assumptions I may have made in my very meager bit of code. Thank you for you time.

Upvotes: 1

Views: 3087

Answers (5)

Jared Ng
Jared Ng

Reputation: 5071

When you're reading in from a file like that, you should use chomp() when doing a comparison with that line. When you do:

print $address[0];
print $address[1];

The output is on two separate lines, even though you haven't explicitly printed a newline. That's because $address[$i] contains a newline at the end. chomp removes this.

if ($address[$i] eq $ipaddress)

could read

my $currentIP = $address[$i];
chomp($currentIP);
if ($currentIP eq $ipaddress)

Once you're familiar with chomp, you could even use:

chomp(my $currentIP = $address[$i]);
if ($currentIP eq $ipaddress)

Also, please replace the goto with a last statement. That's perl's equivalent of C's break.

Also, from your comment on Jack's answer:

Here's some code you can use for finding how long it's been since a file was modified:

my $secondsSinceUpdate = time() - stat('filename.txt')->mtime;

Upvotes: 1

evil otto
evil otto

Reputation: 10582

When you read from a file like that you include the end-of-line character (generally \n) in each element. Use chomp @address; to get rid of it.

Also, use last; to exit the loop; goto is practically never needed.

Here's a rather idiomatic rewrite of your code. I'm excluding some of your logic that you might need, but isn't clear why:

$ipaddress = '192.43.2.130'
open (FH, "serverips.txt") or die "Crossroads could not find a list of backend servers";
while (<FH>) {                  # loop over the file, using the default input space
    chomp;                      # remove end-of-line
    last if ($_ eq $ipaddress); # a RE could easily be used here also, but keep the exact match
}
close(FH);
$file = "server_$.";            # $. is the line number - it's not necessary to keep track yourself
print "The file is $file\n";

Some people dislike using perl's implicit variables (like $_ and $.) but they're not that hard to keep track of. perldoc perlvar lists all these variables and explains their usage.

Regarding the exact match vs. "RE" (regular expression, or regexp - see perldoc perlre for lots of gory details) -- the syntax for testing a RE against the default input space ($_) is very simple. Instead of

last if ($_ eq $ipaddress);

you could use

last if (/$ipaddress/);

Although treating an ip address as a regular expression (where . has a special meaning) is probably not a good idea.

Upvotes: 0

user554546
user554546

Reputation:

First of all, please don't use goto. Every time you use goto, the baby Jesus cries while killing a kitten.

Secondly, your code is a bit confusing in that you seem to be populating @address after starting the if($address[0] == '') statement (not to mention that that if should be if($address[0] eq '')).

If you're trying to compare each element of @address with $ipaddress for equality, you can do something like the following

Note: This code assumes that you've populated @address.

my $num_matches=0;
foreach(@address)
{
  $num_matches++ if $_ eq $ipaddress;
}

if($num_matches)
{
  #You've got a match!  Do something.
}
else
{
  #You don't have any matches.  This may or may not be bad.  Do something else.
}

Alternatively, you can use the grep operator to get any and all matches from @address:

my @matches=grep{$_ eq $ipaddress}@address;
if(@matches)
{
  #You've got matches.
}
else
{
  #Sorry, no matches.
}

Finally, if you're using a version of Perl that is 5.10 or higher, you can use the smart match operator (ie ~~):

if($ipaddress~~@address)
{
  #You've got a match!
}
else
{
  #Nope, no matches.
}

Upvotes: 0

Cfreak
Cfreak

Reputation: 19309

if ($address[0] == ' ')
{
open (FH, "serverips.txt") or die "Crossroads could not find a list of backend servers";
@address = <FH>;
close(FH);

You have several issues with this code here. First you should use strict because it would tell you that @address is being used before it's defined and you're also using numeric comparison on a string.

Secondly you aren't creating an array of the address in the file. You need to loop through the lines of the file to add each address:

my @address = ();
while( my $addr = <FH> ) {
     chomp($addr); # removes the newline character 
     push(@address, $addr);
}

However you really don't need to push into an array at all. Just loop through the file and find the IP. Also don't use goto. That's what last is for.

while( my $addr = <FH> ) {
     chomp($addr);
     if( $addr eq $ipaddress ) {
           $file = "server_$i";
           print $addr,"\n";
           print "I got here first"; # not sure what this means
           last; # breaks out of the loop
     }
}

Upvotes: 3

joemooney
joemooney

Reputation: 1507

You probably are having an issue with newlines. Try using chomp($address[$i]).

Upvotes: 0

Related Questions