Perl: Searching a file - perl

I am creating a perl script that takes in the a file (example ./prog file)
I need to parse through the file and search for a string. This is what I thought would work, but it does not seem to work. The file is one work per line containing 50 lines
#array = < >;
print "Enter the word you what to match\n";
chomp($match = <STDIN>);
foreach $line (#array){
if($match eq $line){
print "The word is a match";
exit
}
}

You're chomping your user input, but not the lines from the file.
They can't match; one ends with \n the other does not. Getting rid of your chomp should solve the problem. (Or, adding a chomp($line) to your loop).
$match = <STDIN>;
or
foreach $line (#array){
chomp($line);
if($match eq $line){
print "The word is a match";
exit;
}
}
Edit in the hope that the OP notices his mistake from the comments below:
Changing eq to == doesn't "fix" anything; it breaks it. You need to use eq for string comparison. You need to do one of the above to fix your code.
$a = "foo\n";
$b = "bar";
print "yup\n" if ($a == $b);
Output:
yup

Related

Perl script - Confusing error

When I run this code, I am purely trying to get all the lines containing the word "that" in them. Sounds easy enough. But when I run it, I get a list of matches that contain the word "that" but only at the end of the line. I don't know why it's coming out like this and I have been going crazy trying to solve it. I am currently getting an output of 268 total matches, and the output I need is only 13. Please advise!
#!/usr/bin/perl -w
#Usage: conc.shift.pl textfile word
open (FH, "$ARGV[0]") || die "cannot open";
#array = (1,2,3,4,5);
$count = 0;
while($line = <FH>) {
chomp $line;
shift #array;
push(#array, $line);
$count++;
if ($line =~ /that/)
{
$output = join(" ",#array);
print "$output \n";
}
}
print "Total matches: $count\n";
Don't you want to increment your $count variable only if the line contains "that", i.e.:
if ($line =~ /that/) {
$count++;
instead of incrementing the counter before checking if $line contains "that", as you have it:
$count++;
if ($line =~ /that/) {
Similarly, I suspect that your push() and join() calls, for stashing a matching line in #array, should also be within the if block, only executed if the line contains "that".
Hope this helps!

Perl, ne operator not working

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;
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.
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.
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?
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.

Perl wont recognize my if statement

my code:
#!/usr/bin/perl
$line = <STDIN>;
if ($line eq "/n") {
print "That was just a blank line!";
} else {
print "That line of input was: $line";
}
it wont recognize when $line in empty or /n. it will just output "That line of input was:" and then it will be nothing, empty. but it will print text if $line actually is something.
It's "\n" to create a newline.
You should rather try the following so that it matches the blank lines with empty spaces
if ($line =~ /^\s+$/)

perl script miscounting because of empty lines

the below script is basically catching the second column and counting the values. The only minor issue I have is that the file has empty lines at the end (it's how the values are being exported) and because of these empty lines the script is miscounting. Any ideas please? Thanks.
my $sum_column_b = 0;
open my $file, "<", "file_to_count.txt" or die($!);
while( my $line = <$file>) {
$line =~ m/\s+(\d+)/; #regexpr to catch second column values
$sum_column_b += $1;
}
print $sum_column_b, "\n";
I think the main issue has been established, you are using $1 when it is not conditionally tied to the regex match, which causes you to add values when you should not. This is an alternative solution:
$sum_column_b += $1 if $line =~ m/\s+(\d+)/;
Typically, you should never use $1 unless you check that the regex you expect it to come from succeeded. Use either something like this:
if ($line =~ /(\d+)/) {
$sum += $1;
}
Or use direct assignment to a variable:
my ($num) = $line =~ /(\d+)/;
$sum += $num;
Note that you need to use list context by adding parentheses around the variable, or the regex will simply return 1 for success. Also note that, like Borodin says, this will give an undefined value when the match fails, and you must add code to check for that.
This can be handy when capturing several values:
my #nums = $line =~ /(\d+)/g;
The main problem is that if the regex does not match, then $1 will hold the value it received in the previous successful match. So every empty line will cause the previous line to be counted again.
An improvement would be:
my $sum_column_b = 0;
open my $file, "<", "file_to_count.txt" or die($!);
while( my $line = <$file>) {
next if $line =~ /^\s*$/; # skip "empty" lines
# ... maybe skip other known invalid lines
if ($line =~ m/\s+(\d+)/) { #regexpr to catch second column values
$sum_column_b += $1;
} else {
warn "problematic line '$line'\n"; # report invalid lines
}
}
print $sum_column_b, "\n";
The else-block is of course optional but can help noticing invalid data.
Try putting this line just after the while line:
next if ( $line =~ /^$/ );
Basically, loop around to the next line if the current line has no content.
#!/usr/bin/perl
use warnings;
use strict;
my $sum_column_b = 0;
open my $file, "<", "file_to_count.txt" or die($!);
while (my $line = <$file>) {
next if (m/^\s*$/); # next line if this is unsignificant
if ($line =~ m/\s+(\d+)/) {
$sum_column_b += $1;
}
}
print "$sum_column_b\n";

Comparing 2 strings, one from file and one declared

This program doesn't print that the strings are equal but when they get printed, they appear to be the same...someone please explain
#!/usr/bin/perl
$str = "print \"I want this to work\\n\";";
print $str."\n";
open FILE, "<", "check2.doc" or die "buhuhuhu";
my $str2;
while (<FILE>) {
$str2 = $_;
}
close FILE;
print "$str2\n";
if ( $str eq $str2) {
print "they are equal\n";
But when the output comes there is this extra line at the bottom due to the second string $str2
print "I want this to work\n";
print "I want this to work\n";
-----empty line-----
Here is the file check2.doc
print "I want this to work\n";
Does anyone know why they are not equal???
The file read includes the \n, so you have to remove it:
$str2 = $_;
chomp $str2;
And, if your file has only one line, replace the while loop by:
$str2 = <FILE>;
chomp $str2;
The line in the file is created by
$str."\n"
Of course that's not equal to
$str
You need to remove the trailing newline.
my $str2 = <FILE>;
chomp($str2);