March 29 (Monday) April 02 (Friday)
Like C's fopen()
and fclose()
function, Perl
supports a means of doing input and output to a file. To demonstrate
File I/O in Perl, consider the following script:
#!/usr/bin/perl -w
use strict;
my ($passwd, $results) = qw< /etc/passwd results.out >;
my %shells;
open FILE, $passwd or die "Cannot open password file: $!\n";
while (<FILE>) {
chomp;
next if /ppp/;
$shells{(split /:/)[-1]} ++;
}
close FILE or die "Cannot close password file: $!\n";
open RES, "> $results" or die "Cannot open '$results' for write: $!\n";
for (sort { $shells{$b} <=> $shells{$a} } keys %shells ) {
print RES "$_: $shells{$_}\n";
}
close RES or die "Cannot close $results'";
fio.pl
There are several things to note about the above script:
open
function.
This function typically takes two arguments: a file handle and a
scalar representing the name of the file in the file system to open.
The file handle represents the connection between your Perl script
and the file itself and is typically written in all capital letters.
We've already seen one file handle already: STDIN
.
By default, open
will open the file for read access.
We'll see opening for write access later.
If the open
call fails, it will return a false value.
Because the open
function is being called as part of an
or
logical operation, the second statement to the right of
the or
operation will have to be evaluated in this case.
This statement causes termination of the program. This is a very common
idiom in Perl.
Note that the or
logical operator is of lower precedence
than the traditional ||
operator. If we wanted to use
the more conventional ||
operator, we would have to put
the parameters of open
in parenthesis in order to ensure
that the precedence of the operators inside the statement make sense.
open (FILE, $passwd) || die "Cannot open password file: $!\n";
A lot of (older) Perl code uses the ||
operator but
using or
in the above context seems to be increasing
in popularity.
$!
special variable used in the string argument to
the die
function will be interpolated to an error message
that explains why the most recent function call failed. In the
code above, the $!
variable will contain a string that
indicates why the script was not able to open the file. For example, if
we tried to open a file for which we did not have read permission, then
$!
will be set to the string: Permission denied
.
If the file did not exist, then $!
will be set to No
such file or directory
. The contents of the $!
variable are quite useful and should be displayed when one of Perl's
functions fail for some reason.
<FILE>
can be used to read a line
from the file handle denoted by FILE
. Again, we've
seen this notation before when reading lines from STDIN
.
Because we are using the <FILE>
notation inside
a while
condition, the $_
default variable
will be set to each line in the opened file on each iteration through
the loop.
chomp
the
line, we skip over lines that have ppp
in them. We then
increment a hash counter. The key in this has is the shell that is used
by the user read in from the passwd
file. Note that the
statement (split /:/)[-1]
will do two things: It will first
split the line of input using the regular expression :
as a
delimiter (each line of the passwd
is delimited by colons).
The result of the split
function is an array of elements.
The statement will then use the indexing operator to access the last
element in this array. Using a negative number the square brackets is a
simple way of indexing an list starting from the back end of the list.
Note that the parentheses around the call to split
are
compulsory, since the indexing operation must operate on the list that
the split function generates.
close
function on the filehandle
that we opened earlier. While it is not too common, the close
operation can fail so it should be tested like the open
function just to be safe, although in practice this is rarely done.
$result
scalar
which will be used to store the results of the script. When opening a
file for write access, we give the filename the special first character
of >
. This will cause Perl to open the filename for
write, thereby overwriting the file if it existed earlier. As with
opening for read, we implicitly check the result of the open
operation and die
(with an appropriate error message using
$!
) if we were unable to open the file for write access
print
(or
printf
) function in a special manner: The first argument
to the print
function is the name of the file handle with
which we opened the file. The second argument is a list representing
the information that we want to store in the file.
print RES "$_: $shells{$_}\n"; # NO comma following RES!!
Note that there is no comma separating the file handle from the list. This last point is very important.
Last modified: March 29, 2004 17:36:39 NST (Monday)