4

I've created this script below for a assignment I have. It asks for a text file, checks the frequency of words, and lists the 10 words that appear the most times. Everything is working fine, but I need this script to be able to start via the command line as well as via the standard input.

So I need to be able to write 'perl wfreq.pl example.txt' and that should start the script and not ask the question for a text file. I'm not sure how to accomplish this really. I think I might need a while loop at the start somewhere that skips the STDIN if you give it the text file on a terminal command line.

How can I do it?

The script

#! /usr/bin/perl

use utf8;
use warnings;

print "Please enter the name of the file: \n" ;
$file = <STDIN>;
chop $file;


open(my $DATA, "<:utf8", $file) or die "Oops!!: $!";
binmode STDOUT, ":utf8";

while(<$DATA>) {
    tr/A-Za-z//cs;
    s/[;:()".,!?]/ /gio;
    foreach $word (split(' ', lc $_)) {
        $freq{$word}++;
    }
}

foreach $word (sort { $freq{$b} <=> $freq{$a} } keys %freq) {
   @fr = (@fr, $freq{$word});
   @ord = (@ord, $word);
}

for ($v =0; $v < 10; $v++) {
    print " $fr[$v] | $ord[$v]\n";
}

4 Answers 4

10

Instead of reading from <STDIN>, you can read from <> to get data either from files provided on the command line or from stdin if there are no files.

For example, with the program:

#!/usr/bin/env perl

while (<>) {
  print $_;
}

The command ./script foo.txt will read and print lines from foo.txt, while ./script by itself will read and print lines from standard input.

Sign up to request clarification or add additional context in comments.

Comments

7

You need to do the following:

my $DATA;
my $filename = $ARGV[0];
unless ($filename) {
    print "Enter filename:\n";
    $filename = <STDIN>;
    chomp $filename;
}
open($DATA, $filename) or die $!;

Though I have to say, user-prompts are very un-Unix like.

3 Comments

This works great and looks like what I was trying for. my $DATA; my $file = $ARGV[0]; if ($file) { open($DATA, $file) or die $!; } else { print "Please enter the name of the file: \n" ; $DATA = STDIN; } I can get it to start via a command line arg now, but when I start it without one it only asks for the file, but never acually goes through the rest of the script and does the sorting and printing. (works with "perl wfreq2.pl example.txt" but not when using "perl wfreq2.pl")
Not really sure what I'm doing wrong, but I can't get it to start when just stating "perl wfreq.pl" it does ask for the file as a STDIN but it's not moving that along and doing the actual sorting and listing.
@FictionFighter Dave Sherohman's answer is the one you should use. Using the diamond <> operator is the way to go.
0
perl script.pl < input.txt

The use of the operator < passes input.txt to script.pl as standard input. You can then skip querying for the filename. Otherwise, use $ARGV[0] or similar, if defined.

5 Comments

That only gives me error messages. adm@adm-desktop:~/Desktop/perl$ perl wfreq2.pl < example.txt Please enter the name of the file: Oops!!: No such file or directory at wfreq2.pl line 11, <STDIN> line 1.
As I said, skip querying for the filename and just loop over <> in the while loop.
Is there something (ie the name of another file) in input.txt?
This is way more complicated than it needs to be, honestly. Read up on "perl standard input" on your favorite search engine.
No the input textfile consist of list of random words that are to be counted and listed.
0

You can check for a command-line argument in @ARGV, which is Perl's array that automagically grabs command line arguments, and --if present-- process them (else continue with input from STDIN). Something like:

use utf8;
use strict;  #Don't ever forget this!  Always, always, ALWAYS use strict!
use warnings;

if(@ARGV)
{
  #Assume that the first command line argument is a file to be processed as in your original code.
  #You may or may not want to care if additional command line arguments are passed.  Up to you.
}
else
{
  #Ask for the filename and proceed as normal.
}

Note that you might want to isolate the code for processing the file name (i.e., the opening of DATA, going through the lines, counting the words, etc.) to a subroutine that you can easily call (perhaps with an argument consisting of the file name) in each branch of the code.

Oh, and to make sure I'm clear about this: always use strict and always use warnings. If you don't, you're asking for trouble.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.