distro distro - 20 days ago 7
Perl Question

Need something like open OR DIE except with chomp

I'm fairly new to coding and I need a fail statement to print out as if it were an or die.

Part of my code for an example:

print "Please enter the name of the file to search:";
chomp (my $filename=<STDIN>) or die "No such file exists. Exiting program. Please try again."\n;

print "Enter a word to search for:";
chomp (my $word=<STDIN>);


I need it to do it for both of these print/chomp statements. Is there anyway to just add on to this?

Whole program:

#!/usr/bin/perl -w

use strict;

print "Welcome to the word frequency calculator.\n";
print "This program prompts the user for a file to open, \n";
print "then it prompts for a word to search for in that file,\n";
print "finally the frequency of the word is displayed.\n";
print " \n";

print "Please enter the name of the file to search:";
while (<>){
print;
}

print "Enter a word to search for:";
chomp( my $input = <STDIN> );

my $filename = <STDIN>;

my$ctr=0;
foreach( $filename ) {
if ( /\b$input\b/ ) {
$ctr++;
}
}
print "Freq: $ctr\n";

exit;

Answer

You don't need to test the filehandle read <> for success. See I/O Operators in perlop. When it has nothing to read it returns an undef, which is precisely what you want so your code knows when to stop reading.

As for removing the newline, you want to chomp separately anyway. Otherwise, once the read does return an undef you'd chomp on an undefined variable, triggering a warning.

Normally, with a filehandle $fh opened on some resource, you'd do

while (my $line = <$fh>) {
    chomp $line;
    # process/store input as it comes ...
}

This can be STDIN as well. If it is certainly just one line

my $filename = <STDIN>;
chomp $filename;

You don't need to test chomp against failure either.

To add, it is a very good practice to always test! Please make sure to always use warnings;, and I also strongly recommend coding with use strict;.


Update to a significant question edit

In the first while loop you do not store the filename anywhere. Given the greeting that is printed, instead of that loop you should just read the filename. Then you read the word to search for.

# print greeting

my $filename = <STDIN>;
chomp $filename;

my $input = <STDIN>;
chomp $input;

However, then we get to the bigger problem: you need to open the file, and only then can you go through it line by line and search for the word. This is where you'll need the test. See the linked doc page and the tutorial perlopentut. First check whether that file exists.

if (not -e $filename) {
    print "No file $filename. Please try again.\n";
    exit;
}

open my $fh, '<', $filename  or die "Can't open $filename: $!";

while (my $line = <$fh>) 
{
    # Now search for the word on a line
    if ($line =~ /\b$input\b/) {
        # ...
    }
}
close $fh  or die "Can't close filehandle: $!";

The -e above is one of the file-tests, this one checking whether the given file exists. See the doc page for file-tests (-X). In the code above we just exit with a message, but you may want to print the message prompting the user to enter another name, in a loop.

I'd like to also strongly suggest to always start your programs with

use warnings 'all';
use strict;