This and other RFCs are available on the web at
http://dev.perl.org/rfc/
=head1 TITLE
Angle brackets should accept filenames and lists
=head1 VERSION
Maintainer: Jon Ericson <[EMAIL PROTECTED]>
Date: 6 August 2000
Version: 1
Mailing List: [EMAIL PROTECTED]
Number: 51
=head1 ABSTRACT
If the file-globbing behavior of angle brackets is
removed (RFC 34), enclosing a non-filehandle will be
undefined. Perl should treat non-filehandles as
filenames and Do What I Mean. Also, angle brackets
should should handle lists (of filenames and
filehandles).
=head1 DESCRIPTION
=head2 Background
>From perlop/"I/O Operators":
In scalar context, evaluating a filehandle in angle brackets yields
the next line from that file (the newline, if any, included), or
C<undef> at end-of-file or on error. When C<$/> is set to C<undef>
(sometimes known as file-slurp mode) and the file is empty, it
returns C<''> the first time, followed by C<undef> subsequently.
[snipped use of angle brackets in a while loop and predefined filehandles]
If a <FILEHANDLE> is used in a context that is looking for
a list, a list comprising all input lines is returned, one line per
list element. It's easy to grow to a rather large data space this
way, so use with care.
<FILEHANDLE> may also be spelled C<readline(*FILEHANDLE)>.
See L<perlfunc/readline>.
The null filehandle <> is special: it can be used to emulate the
behavior of B<sed> and B<awk>. Input from <> comes either from
standard input, or from each file listed on the command line. Here's
how it works: the first time <> is evaluated, the @ARGV array is
checked, and if it is empty, C<$ARGV[0]> is set to "-", which when opened
gives you standard input. The @ARGV array is then processed as a list
of filenames. The loop
while (<>) {
... # code for each line
}
is equivalent to the following Perl-like pseudo code:
unshift(@ARGV, '-') unless @ARGV;
while ($ARGV = shift) {
open(ARGV, $ARGV);
while (<ARGV>) {
... # code for each line
}
}
except that it isn't so cumbersome to say, and will actually work.
It really does shift the @ARGV array and put the current filename
into the $ARGV variable. It also uses filehandle I<ARGV>
internally--<> is just a synonym for <ARGV>, which
is magical. (The pseudo code above doesn't work because it treats
<ARGV> as non-magical.)
You can modify @ARGV before the first <> as long as the array ends up
containing the list of filenames you really want. Line numbers (C<$.>)
continue as though the input were one big happy file. See the example
in L<perlfunc/eof> for how to reset line numbers on each file.
If you want to set @ARGV to your own list of files, go right ahead.
This sets @ARGV to all plain text files if no @ARGV was given:
@ARGV = grep { -f && -T } glob('*') unless @ARGV;
You can even set them to pipe commands. For example, this automatically
filters compressed arguments through B<gzip>:
@ARGV = map { /\.(gz|Z)$/ ? "gzip -dc < $_ |" : $_
} @ARGV;
If you want to pass switches into your script, you can use one of the
Getopts modules or put a loop on the front like this:
while ($_ = $ARGV[0], /^-/) {
shift;
last if /^--$/;
if (/^-D(.*)/) { $debug = $1 }
if (/^-v/) { $verbose++ }
# ... # other switches
}
while (<>) {
# ... # code for each line
}
The <> symbol will return C<undef> for end-of-file only once.
If you call it again after this, it will assume you are processing another
@ARGV list, and if you haven't set @ARGV, will read input from STDIN.
=head2 Easy things should be easy
Input from a file is already easy in Perl, but it
could be easier.
=head2 Flexibility
As noted above, the behavior this RFC proposes is
already partially availible with @ARGV and <>. But
you can't mix filenames with filehandles. Nor is it
obvious what you are doing. And it takes two steps.
=head1 IMPLEMENTATION
Let:
while (<LIST>) {
# code for each line
}
be "equivalent to the following Perl-like pseudo code":
@ARGV = LIST;
unshift(@ARGV, '-') unless @ARGV;
while ($ARGV = shift) {
my $fh;
if (ref $ARGV eq 'GLOB'){ # or filehandle ref result
$fh = $ARGV;
}else{ # should we include other cases (e.g. array refs)?
open($fh, $ARGV) or warn "can't open $ARGV: $!";
};
while (<$fh>) {
# code for each line
};
};
=head1 REFERENCES
RFC 34 - Angle brackets should not be used for file globbing.
perlop/"I/O Operators"