in reply to input from STDIN or from a file

Erm, you are aware that using just <> does pretty much the same thing already? Not to mention that while( <$ifh> ) { ... } isn't going to return false until there's an EOF condition on STDIN in which case you're not really going to gain much by not closing it (at least nothing useful that I can think of off hand).

The cake is a lie.
The cake is a lie.
The cake is a lie.

Replies are listed 'Best First'.
Re^2: input from STDIN or from a file
by citromatik (Curate) on Jan 28, 2008 at 18:02 UTC
    Erm, you are aware that using just <> does pretty much the same thing already?

    Yes, that's right, but in this particular script I use my filehandles in a closure:

    sub get_closure { my ($filename) = @_; open my $ifh, "<", $filename or die $!; return sub { # subroutine that returns one record per call } } # and then: my $getNextRecord = get_closure($filename); while ( my $record = $getNextRecord->() ){ # do something with $record }

    Yes, I know that this sounds paranoic, but I find some benefits using this (private filehandles, a bit of encapsulation, access to $ifh a bit faster, etc...

    Given this scenario I don't know if using <> is easy or even possible.

    Not to mention that while( <$ifh> ) { ... } isn't going to return false until there's an EOF condition on STDIN in which case you're not really going to gain much by not closing it (at least nothing useful that I can think of off hand).

    Sure, I agree, but you can have something like this:

    my $file = shift @ARGV; my $ifh; my $is_stdin = 0; if (defined $file){ open $ifh, "<", $file or die $!; } else { $ifh = *STDIN; $is_stdin++; } while (<$ifh>){ # Process } #close $ifh unless $is_stdin; close $ifh; ## code passes... ## ... and my $another_value = <STDIN>;

    If you happen to close STDIN, that last statement would give you an error.

    Ok, I will stop here, or you will think that I'm really a paranoic :-)

    citromatik
Re^2: input from STDIN or from a file
by citromatik (Curate) on Jan 28, 2008 at 19:58 UTC

    also, there is a subtle difference between the <> operator and the implementation showed in the original post (although not very useful I think).

    consider this:

    $ cat test1.pl #!/usr/bin/perl use strict; use warnings; while (<>){ print; } $ cat > testfile two three $ echo "one" | perl test1.pl testfile one two three $ cat test2.pl #!/usr/bin/perl use strict; use warnings; my $file = shift @ARGV; my $ifh; my $is_stdin = 0; if (defined $file){ open $ifh, "<", $file or die $!; } else { $ifh = *STDIN; $is_stdin++; } while (<$ifh>){ print } close $ifh unless $is_stdin; $ echo "one" | perl test2.pl testfile two three

    That is, the <> operator acts like:

    unshift(@ARGV, '-') unless @ARGV; while ($ARGV = shift) { open(ARGV, $ARGV); while (<ARGV>) { ... # code for each line } }

    i.e. processes STDIN AND any file given in the command line, while my implementation processes the file given in the command line OR STDIN.

    citromatik

      Erm, no it does either arguments or STDIN if none were given just like the documentation in perlop and the code you copied there from says. Read it again:

      unshift( @ARGV, '-' ) unless @ARGV;

      Put a string '-' (which is shorthand to open to read from STDIN) onto the front of @ARGV unless there are already arguments in @ARGV.

      If you're getting the behavior you're seeing out of your test1.pl then something very strange is going on.

      $ cat my_test1.pl #!/usr/bin/perl use strict; use warnings; while (<>){ print; } $ cat infile 2 from infile 3 from infile $ echo "testing" | perl my_test1.pl infile 2 from infile 3 from infile

      The cake is a lie.
      The cake is a lie.
      The cake is a lie.