Quick code review:
use strict;
use warnings;
A very good choice. These pragmas provide information about your code, and help you avoid mistakes.
my $search = <>;
Here you take the first line of the input as the search string. This is probably not what you want. If you are searching through a file, I am guessing the file does not contain the search word in the first line. What you probably are trying to do is access the command line arguments, which are found in @ARGV
.
my $search = shift;
This is the idiomatic way to access @ARGV
. It is short for shift @ARGV
, which takes the first argument off @ARGV
.
while (defined(my $file = <>)) {
chomp($file);
my $filesize = length $file;
I get the impression that you think that $file
is actually the file name. You said you tried -s $file
, which would have worked, if $file
had contained the file name. However, the while loop reads from the input file handle <>
and assigns the lines of the file to $file
. If you want to access the file name, you probably want $ARGV
. And you only want to do this once, after the while loop:
my $filesize = -s $ARGV;
Keep in mind that if you use more than one file, $ARGV
will change as it refers to the name of the file currently being read with <>
. (Technically <ARGV>
)
The while loop itself should probably use a different variable name:
while (my $line = <>)
Note that you do not technically need to use defined
here.
Also, length
returns the number of characters in a string. If you use it on a file name, it returns the number of characters in the file name. It has nothing to do with file size.
if (m/$search/){
my $wordcount++;
}
This pattern match applies to the default variable $_
. What you want is $file =~ m/..../
. Also, do you want meta characters to be active in the regex? You might want, for example, to allow plural s
with /apples?/
. Meta characters can change the meaning of your pattern match, however, so if you just want to match literal strings, use the \Q ... \E
escape to disable meta characters.
Another thing, you use my
here to declare a new variable (which shadows the previously declared variable). This variable only has the scope of the surrounding if
block, so it is quite pointless. Remove my
.
Yet another thing is that this match only matches once per line, so you miss out on multiple matches. What you want is probably this:
$wordcount += () = $line =~ /\Q$search\E/g;
Note the use of the global /g
modifier which makes the regex match as many times as possible (and not just once). Using ()
in scalar context returns the number of matches from the pattern match.
$linecount = 1;
$linecount++;
This sets the count to 2. No matter how many lines are in your file, this will never be more than 2. You want to remove the assignment.