monkfan has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,
I wanted my code to be able to accept the input flexibly, either from PIPE:
$ perl othercode.pl | perl thiscode.pl
or from STDIN
$ perl thiscode.pl SOMEFILE.txt
Currently I have this construct. But is there a better way to do it?
#!/usr/bin/perl -w use strict; # thiscode.pl my $file = $ARGV[0]; my @lines; if($file) {@lines = `cat $file`;} else {@lines = <STDIN>;} # Update: Also, can I do better than 'slurping' +here? foreach (@lines) { #Do my stuff here }
Regards,
Edward

Replies are listed 'Best First'.
Re: How to accept ARG from PIPE or STDIN?
by moot (Chaplain) on Mar 17, 2005 at 01:05 UTC
    How about just
    @lines = <>;
    Your second example is not reading from STDIN, by the way. You probably meant this:
    $ perl thiscode.pl < SOMEFILE.txt

    Update: Your first example, using the pipe, is reading from STDIN.. but the magic diamond <> works for both named arguments (files listed) and STDIN.

Re: How to accept ARG from PIPE or STDIN?
by perlfan (Parson) on Mar 17, 2005 at 02:17 UTC
    while (<>) { # do something with $_ }
    This will, assuming $\ has not been messed with, loop for each line of input via:
    # cat myfile.txt | dosomething.pl
    and
    # dosomething.pl < myfile.txt
    If you wanted to do:
    #dosomething.pl myfile.txt
    You need to get the filename from the first element in @ARGV, the arguments array. You may also want to check out Multiple STDIN sources.

      If you wanted to do:

      dosomething.pl myfile.txt

      You need to get the filename from the first element in @ARGV, the arguments array. You may also want to check out Multiple STDIN sources.

      No. <> treats as a list of file names, and opens each of them in turn. <> only reads from STDIN if @ARGV is empty. In other words,

      while (<>) { # do something with $_ }

      works for all of the following:

      cat myfile.txt | dosomething.pl dosomething.pl < myfile.txt dosomething.pl myfile.txt
        But how about, if I want to use "die" command in this standard context?
        open INFILE, "<$file" or die "$0: Can't open file $file: $!"; while (<INFILE>){ # do something with $_ }
        Does it still work?
        Regards,
        Edward
Re: How to accept ARG from PIPE or STDIN?
by Fletch (Bishop) on Mar 17, 2005 at 04:14 UTC

    You could always use the special filename "-" to indicate it should read from STDIN. See "The Minus File" in perldoc perlopentut.