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

Maybe this is more of a meditation than a SoPW-question. In fact I know "How TDI", but I'm curious as to know which strategy people would prefer, all in all.

Basically I have this small sized script which accepts a list of filenames on the cmd line. The first file should be processed differently from the other ones (which as usual may be substituted by STDIN).

One obvious approach could be

#!/usr/bin/perl use strict; use warnings; die "Usage: $0 <file> [<files>]\n" unless @ARGV; open my $fh, '<', shift or die $!; while (<$fh>) { # ... } while (<>) { # ... } __END__
But I'm keen on iterating on ARGV and I was thinking of
while (<>) { # ... last if eof(ARGV); } while (<>) { # ... }
too. (Of course the latter has the disadvantage of doing an additional check at each iteration.)

Now it would be nice if there was an ARGV variant allowing one to iterate on the FH associated to the current $ARGV only, but since there is none available AFAIK, how would you do it?

Replies are listed 'Best First'.
Re: How would you do it? Re ARGV, fundamentally!
by merlyn (Sage) on Jul 19, 2005 at 11:38 UTC
        I may be seen as the poster-boy for "make it shorter", but this line:
        local @ARGV=shift;
        has a huge pile o' magic going on in it. While I might use it in a program, it deserves a comment line alongside it, explaining that the "shift" on the right side is using the old @ARGV, before the new local @ARGV is created.

        No, in production code, I'd probably write it like I showed upthread. Yours is full of magic.

        -- Randal L. Schwartz, Perl hacker
        Be sure to read my standard disclaimer if this is a reply.

Re: How would you do it? Re ARGV, fundamentally!
by inman (Curate) on Jul 19, 2005 at 11:36 UTC
    The while (<>) {} idiom is useful when you want your script to process data from a number of files, or from STDIN (piped, redirected, typed) and have it treated in the same way regardless. The diamond operator is provided as a shortcut. If the shortcut doesn't work for you then you will need to work with explicitly opened file handles.

    Modules such as Getopt::Long extract named command line arguments and remove them from @ARGV so that you are able to work with whatever remains in @ARGV. A typical script will use Getopt::Long, extract special parameters, work with what's left. E.g.

    #! /usr/bin/perl # # A simple file catenation # # use strict; use warnings; use Getopt::Long; my $target; my $debug; # Get optional args first my $result = GetOptions ("target=s" => \$target, # string "debug" => \$debug); # flag # The target filename is the first filename if it hasn't already been +set. $target = shift @ARGV unless $target; open TARGET, ">$target" or die "unable to open $target [$!]\n"; foreach my $src (@ARGV) { open SRC, "<$src" or die "unable to open $src [$!]\n"; while (<SRC>) { # Do something with the files. print TARGET; print if $debug; } close SRC; } close TARGET
Re: How would you do it? Re ARGV, fundamentally!
by holli (Abbot) on Jul 19, 2005 at 10:39 UTC
    I never use the while (<>) {} construct. Instead I always use a explicit open, mostly along with a Getopt module. Then I can throw errors with my own error messages and parse additional flags conveniently.


    holli, /regexed monk/
      It all depends on your target application. For some classes of applications while (<>) {} is great. Occasionally I have even filled @ARGV manually to exploit it.