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

i know that you can read all files passed as arguments at once with the diamond operator like this:
while(<>) { //do stuff }
but I want to read the first file as a special case and then the rest of the files with <>.
open FST, $ARGV[0]; while(<FST>) { //do stuff } while(<>) { // other stuff with all files but $ARGV[0] }
how can I do that ?

Replies are listed 'Best First'.
Re: diamond operator
by Corion (Patriarch) on Jun 09, 2009 at 13:22 UTC

    <> reads from @ARGV, so you can just modify @ARGV if you want special behaviour. In your case, remove the first element from @ARGV, or use Getopt::Long to introduce a command line switch.

      thanks for the reply.
      I see, so a shift will do the trick right ?
      shift @ARGV;

      oh jz, reading my post now I realized the C comments..please ignore it, I still learning..
      Update: ran some more code and the first part here is not right.

      Just a little point, <> reads from STDIN, not @ARGV. Looks like a typo to me.

      For the poster, I showed some code below. In Perl @ARGV has the command line args. In C, char **argv, array of pointers to strings. Way easier in Perl! Perl does have equivalent to C getopts with many flavors.

        <> only reads from STDIN if @ARGV is empty:

        @ARGV=($0,$0,$0); print for <>;
Re: diamond operator (eof)
by tye (Sage) on Jun 09, 2009 at 14:30 UTC

    You can nearly do this with just <> and without touching @ARGV. First read eof then consider:

    while( <> ) { print "First: $_"; last if eof; # Stop at end of /first/ file } while( <> ) { print; }

    But this actually does special processing of the first non-empty file, not the first file. Detecting that the first file is non-empty without directly modifying @ARGV is trickier:

    my $args= @ARGV; if( ! eof() # Prime the <> pump && @ARGV == $args-1 # Did we not move past the first file? ) { while( <> ) { print "First: $_"; last if eof; } } while( <> ) { print; }

    In any case, I find it an interesting solution.

    (Updated within seconds of posting to replace a near solution with a real solution.)

    - tye        

      sweet, this first exemple looks quite clean, now I have to choose between poping the @ARGV or an extra if, although my C mind says "no useless if's" I guess I'll use it.
Re: diamond operator
by Marshall (Canon) on Jun 09, 2009 at 16:06 UTC
    You are on the right idea. Perl is different than C in many respects. One noticeable things is that subscripts like $ARGV[0] are strangely absent. Here are some command line things that would call my_prog..

    >perl my_prog somename name2 name3 name4
    >perl my_prog somename name2
    >perl my_prog somename
    >perl my_prog *.txt
    Here is the code:

    #!/usr/bin/perl -w use strict; die "must have at least 2 files\n" if @ARGV <2; my ($first_file, @other_files) = @ARGV; open(IN, '<', "$first_file") || die "can't open $first_file $!"; while (<IN>) { #work on each line in the first file } foreach my $file (@other_files) { open (IN, "<", $file) or die "can't open $file $!"; while (<IN>) { #work on each line in the sub files } }
    BTW:
    - in C $argv[0] is program name, in Perl $0 is, "well sort of" and is more complex than it sounds amongst O/S'es, but that is the basic idea.
    - in Perl @ARGV contains the number of args (could be expanded by shell)