#Files
Perl is at its best when it is processing text and reading and writing files. Open a new Perl script (nano files.pl
) and type the following lines.
$filename = $ARGV[0];
open FILE,"<$filename" or die "Cannot read the file $filename: $!\n";
$i = 0;
while ($line = <FILE>)
{$i = $i + 1;
print "$i : $line";
}
Run this script by passing as an argument the path to any file, e.g.
perl files.pl ./files.pl
What you should see is that Perl has printed out every line of the file, with each line preceeded by its line number. Lets go through each line of the script to see how Perl has achieved this feat
First we got the filename as the first argument to the script via the line $filename = $ARGV[0];
The next step was to open the file. You open files using the open
command. The part open FILE,"<$filename"
says to open the file whose path is the value of the variable $filename
and attach that file to the filehandle FILE
. The less than sign before the filename "<$filename"
tells Perl that you only want to read the file (you won’t be writing to it). This means that there will be an error if the file does not exist, or is not readable. This error is handled by the rest of the line or die "Cannot read the file $filename: $!\n"
. The command die
tells the Perl script to exit with an error (literally keel over and die!), printing the error string which comes after the die
command. The variable $!
is a special variable which has a value equal to the last system error. This variable allows you to get a little more information as to why you can’t read the file.
In the next line $i = 0;
we are just initialising the counter variable $i
so that it is equal to zero.
The next line while ($line = <FILE>)
is interesting. First, it is a while loop. A while loop is like a for loop, except it only has a condition (there is no initialise or increment section). The while loop keeps looping while the condition is true, and only exits when the condition becomes false. In this case the condition is $line = <FILE>
. The reads a single line from the file connected to the filehandle FILE
. The contents of this line is read as a string, which is given as the value of the variable $line
using $line = <FILE>
. This returns true
if there was a line to read, but returns false
if there are no more lines to read. If there are no more lines to read, this is false, so the condition of the while loop is false, so the loop exits. Therefore, this while loop reads in every line of the file, one line at a time, assigning the value of each line to the variable $line
until all of the lines have been read.
In the body of the loop, $i = $i + 1;
just increments the count of how many lines have been read.
Then the line print "$i : $line"
prints the value of the counter and the value of the line. Note that we don’t need to add a \n
onto the end, as the line read in from the file already has its own newline character on the end.
##Exercise
head and tail are two useful UNIX programs that can be used to print out the first few, or last few lines of a file (this is useful if you are monitoring log files). Can you write a Perl script that does the same thing?
For example
perl head.pl 5 filename
should print out the first five lines of a file, and
perl tail.pl 10 filename
should print out the last ten lines of a file.
Answer head.pl and tail.pl. (don’t peek unless you are stuck or until you have finished!)
Can you go one better and write a body
command, that prints the middle of a file? For example
perl body.pl 20 25 filename
prints lines 20 to 25 of a file. Can you write the code so that
perl body.pl 25 20 filename
would print lines 25 to 20 (so reversing the file)? (Hint - you will need to use an array)
Answer. (again, don’t peek until you have finished!)