You didn't check whether open succeeded so you didn't spot that the $input_file is incorrect. See the Basic Debugging Checklist for more like this.
| [reply] [d/l] [select] |
Add in a 'die' function to see why file is not opening:
open my $fh, '<', $input_file or die "Cannot open file: $!";
| [reply] [d/l] |
I think you also want to get the $input_file from the command line?.
I personally have a disdain for while(1) loops and pretty much only use them for servers or similar applications.
I would code the loop ending condition into the while loop. If you don't like the comma operator, a logical and should work also.
#!/usr/bin/perl
use strict;
use warnings;
##############
## 03/14/19
## Exercise reads from file, then lets user interactively submit matc
+hing search criteria
my $input_file = shift @ARGV;
open my $fh, '<', $input_file or die "unable to open $input_file for s
+earching $!";
chomp(my @strings = <$fh>);
my $pattern;
while ( (print 'Please enter a pattern: '),$pattern=<STDIN>, $pattern
+!~ /\A\s*\Z/)
{
chomp $pattern;
my @matches = eval {
grep /$pattern/, @strings;
}; ## end of eval
if ($@) {
print "Error: $@";
} else {
my $count = @matches;
print "There were $count matching strings:\n",
join ("\n",@matches);
}
print "\n";
}
Update: you will notice that I changed a few other things. I don't see anything here that requires Perl >=5.16, so I put in "use strict;". This code should run fine on an ancient Perl. If you use some regex construct that is not available in the Perl being used, your eval will fail at run time which sounds fine to me. Instead of using a map() to add line endings to @matches, I used a join. If Perl has a special function for something, this usually works out faster and makes the code more clear than using a more general, but "heavier weight" mechanism like map. Now that I think about it, there probably isn't any need to take out the line endings in the first place which would render this point mute.
The reason I like my while conditional is that it shows clearly what is going to cause the loop to proceed and what is going to cause it to end (blank line). Note that parens around the print statement is not a typo, they are required here in order to get the characters to the screen "mid way" through the statement. Play with the code using the parens and not using them and you will see what it does. Of course enhancements are possible, like adding an error message if the command line doesn't contain a file name. die "no input file specified!\n" unless defined ($input_file); or whatever, maybe a longer usage message? Just icing on the cake.
Another update on style: In my opinion some of the most important "code" that you can write is "whitespace". Start the high level code at the left margin (you had it indented). Add a blank line when roughly speaking the subject/purpose changes. I put a blank line after getting the input file "ready", after getting the pattern "ready", after using the pattern. Minor quibbles can arise from this - my main point is that whitespace can increase understandability and consumes NO Mips! Consider adding blank lines at places you consider significant "thought transitions". | [reply] [d/l] [select] |
Hello catfish1116,
Fellow Monks already told you the problem to your script. I would also to add a minor modification to possibly use a module IO::All so you do not need to bother with this minor issues and minimize your code on this part.
Sample of modification below:
#!/usr/bin/perl
use strict;
use warnings;
use IO::All;
use v5.16;
##############
## 03/14/19
## Exercise reads from file, then lets user interactively submit matc
+hing search criteria
die "Please provide a file to process!\n" unless (defined $ARGV[0]);
my @lines = io($ARGV[0])->chomp->slurp; # Chomp as you slurp
while (1) {
print 'Please enter a pattern: ';
chomp(my $pattern = <STDIN>);
last if $pattern =~ /\A\s*\Z/;
my @matches = eval {
grep /$pattern/, @lines;
}; ## end of eval
if ($@) {
print "Error: $@";
} else {
my $count = @matches;
print "There were $count matching strings:\n",
map "$_\n", @matches;
}
print "\n";
}
Hope this helps, BR.
Seeking for Perl wisdom...on the process of learning...not there...yet!
| [reply] [d/l] [select] |