0

Can someone please tell me why my ne operator isn't working in the below if statement? It was working but after saving my program, it has stopped working. Any help would be greatly appreciated, cheers.

$inFile = "animals.txt";
open (IN, $inFile) or
die "Can't find file: $inFile";

@animallist = (<IN>);

foreach $line (@animallist)  
{
  if ($line =~ $search)
  {
    print "$line <br> <br>";     
  }
}
if ($line ne $search)
{
  print "$search isn't in the animal list";
}

print end_html;
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
TheHadimo
  • 147
  • 1
  • 1
  • 8
  • 1
    What makes you think its not working? – TLP Nov 17 '14 at 23:02
  • 5
    Always put @ the top: `use strict; use warnings;` – Gilles Quénot Nov 17 '14 at 23:02
  • The first if statement works, but if it finds the word in the file, it also prints the last print statement."$search isn't in the animal list" – TheHadimo Nov 17 '14 at 23:06
  • You realize, since you don't exit your for-loop when you find a line that matches `$search` that it just continues through the file and so when you get to the `if($line ne $search)` part there is no guarantee that `$line` is still the value that matched `$search` in the loop... – scrappedcola Nov 17 '14 at 23:12
  • Yeah but if i put it in within the For loop, then it prints $search isn't in the animal list over and over again – TheHadimo Nov 17 '14 at 23:20
  • 2
    @TheHadimo I don't follow your logic. So if checking each line in the file is wrong, then checking afterwards is correct because....? – TLP Nov 17 '14 at 23:23
  • have you thought of defining the variable $line before the loop, then when you make your match, either breaking the loop execution or storing off the match to another variable/structure? – scrappedcola Nov 17 '14 at 23:29
  • Note a duplicate. The other question doesn't have a for loop in it, and the answer is that for loop vars are scoped to the loop. – ikegami Nov 18 '14 at 03:30

4 Answers4

5

You seem confused about what your program does, so I thought I'd just tell you.

$inFile = "animals.txt";
open (IN, $inFile) or die "Can't find file: $inFile";
@animallist = (<IN>);

# here you define a file name, open a file, and read all of the lines
# in the file into the array @animallist

foreach $line (@animallist) {
# here you iterate over all the lines, putting each line into $line
  if ($line =~ $search) {
    print "$line <br> <br>";     
  }
# here you perform the regex match: $line =~ /$search/ and if it 
# succeeds, print $line
}
# here you end the loop

if ($line ne $search) {
  print "$search isn't in the animal list";
}
# here you take the now uninitialized variable $line and try to match 
# it against the as of yet undefined variable $search
# If both of these variables are undefined, and you are not using warnings
# it will simply return false (because "" ne "" is false)
# without warning about undefined variables in ne

You should be aware that even if your entire line was, for example, cat, you still could not compare it using ne to the string cat, because when read from a file, it has a trailing newline, so it is really cat\n. Unless you chomp it.

It seems redundant to tell you, but of course you cannot check if the file does not contain $search after you finished reading the file. You have to do that while reading the file.

TLP
  • 66,756
  • 10
  • 92
  • 149
  • Re "here you take the now uninitialized variable $line", because foreach loop vars (e.g. `$line`) are only temporarily aliased to each element of the list over which the loop iterates. The aliasing goes away when the loop exits, effectively restoring the variable's original value. In short, `for $var (...) { ... }` makes no sense; always use `for my $var (...) { ... }` – ikegami Nov 18 '14 at 03:34
1

Try using indentation so you can see when your blocks end at inappropriate places.

if ($line ne $search) isn't even within the foreach loop where you are populating and handling $line from the file. I suggest putting it within the block to at least get the functionality I assume you are looking for.

Brandon Kindred
  • 1,468
  • 14
  • 21
  • Yeah but if i put it in within the For loop, then it prints $search isn't in the animal list over and over again – TheHadimo Nov 17 '14 at 23:20
  • It prints it over and over though because those lines don't match and that's what you want it to print when they don't match. I can't do anything about your funny logic, but that's what you are looking for. In general, from what I assume you are trying to accomplish you need to implement a either a boolean flag or a data structure so you can tell if any animals in the list match. Even the if($line ne $search) is probably better as a simple else instead. – Brandon Kindred Nov 18 '14 at 18:39
1

It's hard to know what you expect to happen as we don't know what $search contains. Let's assume it's the name of an animal that is in your file.

When you execute your code, $search contains, say, "frog" and $line contains undef (as $line only contains data within your foreach loop). Those values aren't the same so the ne returns true and the message is printed.

If you were to move that if statement into the foreach block then $line would have a value. But it still wouldn't match as lines are read from a file with the newline character still attached. And "Frog" is not the same as "Frog\n". You need to use chomp() to remove the newline from $line.

This is very similar to another recent question. Are you working on the same piece of homework?

Community
  • 1
  • 1
Dave Cross
  • 68,119
  • 3
  • 51
  • 97
0

I think there are several points here:

  • For the if ($line ne $search), the $line is out of the scope of the foreach where it was declared and since you are not using strict, you won't get error and this condition should always be true.

  • I assume that $line has a newline so when you match this $line with $search, the condition can be true although the strings are not equal.

Assuming that $line = "lion\n" and $search = "lion"

then if you do if ($line =~ $search), the condition will be be true, because "lion" is part of the "lion\n" string. This means that: if ($line eq $search) is false and if ($line ne $search) is true which I assume is your case.

you can use the chomp($line) function to remove newlines from the end of the string.

I hope this helps.