Writing a Filter
Problem
You want to write a program that takes
a list of filenames on the command line and reads from STDIN if no
filenames were given. You’d like the user to be able to give
the file "-"
to indicate STDIN or
"someprogram
|"
to indicate the
output of another program. You might want your program to modify the
files in place or to produce output based on its input.
Solution
Read lines with <>:
while (<>) { # do something with the line }
Discussion
When you say:
while (<>) { # ... }
Perl translates this into:[13]
unshift(@ARGV, '-') unless @ARGV; while ($ARGV = shift @ARGV) { unless (open(ARGV, $ARGV)) { warn "Can't open $ARGV: $!\n"; next; } while (defined($_ = <ARGV>)) { # ... } }
You can access ARGV
and $ARGV
inside the loop to read more from the filehandle or to find the
filename currently being processed. Let’s look at how this
works.
Behavior
If the user supplies no arguments, Perl sets @ARGV
to a single string, "-"
. This is shorthand for
STDIN when opened for reading and STDOUT when opened for writing.
It’s also what lets the user of your program specify
"-"
as a filename on the command line to read from
STDIN.
Next, the file processing loop removes one argument at a time from
@ARGV
and copies the filename into the global
variable $ARGV
. If the file cannot be opened, Perl
goes on to the next one. Otherwise, it processes a line at a time.
When the file runs out, the loop goes back and opens the next one,
repeating the process until @ARGV
is exhausted.
The open
Get Perl Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.