FictionFighter
FictionFighter

Reputation: 97

Perl - Command line input and STDIN

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";
}

Upvotes: 4

Views: 35880

Answers (4)

user468687
user468687

Reputation:

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.

Upvotes: 7

Dave Sherohman
Dave Sherohman

Reputation: 46187

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.

Upvotes: 10

user554546
user554546

Reputation:

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.

Upvotes: 0

Alex Reynolds
Alex Reynolds

Reputation: 96937

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.

Upvotes: 0

Related Questions