Some Files Are Standard
In an effort to make programs more uniform, there are three connections that always exist when your program starts. These are
STDIN,
STDOUT, and
STDERR. Actually, these names are
file handles. File handles are variables used to manipulate files. Just like you need to grab the handle of a hot pot before you can pick it up, you need a file handle before you can use a file. Table 9.1 describes the three file handles.
Table 9.1 - The Standard File Handles Name | Description |
STDIN | Reads program input. Typically this is the computer's keyboard. |
STDOUT | Displays program output. This is usually the computer's monitor. |
STDERR | Displays program errors. Most of the time, it is equivalent to STDOUT, which means the error messages will be displayed on the computer's monitor. |
You've been using the
STDOUT file handle without knowing it for every
print() statement in this book. The
print() function uses
STDOUT as the default if no other file handle is specified. Later in this chapter, in the "Examples: Printing Revisited" section, you will see how to send output to a file instead of to the monitor.
The association of these file handles can be altered
We can also use:< input # STDIN
$ perl prog.pl > output # STDOUT
$ perl prog.pl 2> errors # STDERR
Using STDIN
Reading a line of input from the standard input,
STDIN, is one of the easiest things that you can do in Perl. This following three line program will read a line from the keyboard and then display it. This will continue until you press
Ctrl+Z on DOS systems or
Ctrl-D on UNIX systems.
while (< STDIN >) {
print();
}
The <> characters, when used together, are called the diamond operator. They tell Perl to read a line of input from the file handle inside the operators. In this case, STDIN. Later, you'll use the diamond operators to read from other file handles.
In this example, the diamond operator assigned the value of the input string to $_. Then, the print() function was called with no parameters, which tells print() to use $_ as the default parameter. Using the $_ variable can save a lot of typing but I'll let you decide which is more readable. Here is the same program without using $_.
while ($inputLine = ) {
print($inputLine);
}
When you pressed
Ctrl+Z or
Ctrl+D, you told Perl that the input file was finished. This caused the diamond operator to return the undefined value which Perl equates to false and caused the
while loop to end. In DOS (and therefore in all of the flavors of Windows), 26 - the value of
Ctrl+Z - is considered to be the end-of-file indicator. As DOS reads or writes a file, it monitors the data stream and when a value of 26 is encountered the file is closed. UNIX does the same thing when a value of 4 - the value of
Ctrl+D - is read.
#Making echo command in perl:
#echo0.pl
while (< STDIN >) {
print();
}
#echo1.pl
$line = <STDIN>;
print "echo:$line";
#!/usr/local/bin/perl
# echo2.pl : reads in multiple lines and prints them all
# keeps echoing back what the user types while ( $line = ) { print "echo:$line"; }
$_ as the default input variable
#!/usr/local/bin/perl
# echo3.pl
# keeps echoing back what the user types
while ( ) {
print "echo:$_"; #instead of just writing print(); like in echo0.pl
}
Using Redirection to Change STDIN and STDOUT
DOS and UNIX let you change the standard input from being the keyboard to being a file by changing the command line that you use to execute Perl programs. Until now, you probably used a command line similar to:
perl -w 09lst01.pl
In the previous example, Perl read the keyboard to get the standard input. But, if there was a way to tell Perl to use the file
09LST01.PL as the standard input you could have the program print itself. Pretty neat, huh? Well, it turns out that you can change the standard input. It's done this way:
perl -w 09lst01.pl < 09lst01.pl
The
< character is used to
redirect the standard input to the
09LST01.PL file. You now have a program that duplicates the functionality of the DOS type command. And it only took three lines of Perl code!
You can redirect standard output to a file using the
> character. So if you wanted a copy of
09LST01.PL to be sent to
OUTPUT.LOG you could use this command line:
perl -w 09lst01.pl <09lst01.pl >output.log
Keep this use of the
< and
> characters in mind. You'll be using them again shortly when we talk about the
open() function. The
< character will signify that files should be opened for input and the
> will be used to signify an output file. But first, let's continue talking about accessing files listed on the command line.
Using the Diamond Operator (<>)
If no file handle is used with the diamond operator, Perl will examine the
@ARGV special variable. If
@ARGV has no elements, then the diamond operator will read from
STDIN - either from the keyboard or from a redirected file.
while (<>) {
print();
}
The command line to run the program might look like this:
perl -w 09lst02.pl 09lst01.pl 09lst02.pl
And the output would be:
while () {
print();
}
while (<>) {
print();
}
Perl will create the
@ARGV array from the command line. Each file name on the command line - after the program name - will be added to the
@ARGV array as an element. When the program runs the diamond operator starts reading from the filename in the first element of the array. When that entire file has been read, the next file is read from, and so on, until all of the elements have been used. When the last file has be finished, the
while loop will end.
Using the diamond operator to iterate over a list of filenames is very handy. You can use it in the middle of your program by explicitly assigning a list of filenames to the
@ARGV array. Listing 9.3 shows what this might look like in a program.
@ARGV = ("09lst01.pl", "09lst02.pl");
while (<>) {
print();
}
This program displays:
while () {
print();
}
while (<>) {
print();
}
Next, we will take a look at the ways that Perl lets you test files, and following that, the functions that can be used with files.
Reading into variables in perlThough we have already seen it how to use here is some more detail of it.
Lets suppose we have
handle to read from file handle FILE
– read one line at a time (scalar context)
– read all lines at once (array context)
– returns undef at EOF
Eg.
$first = ; # first line
$second = ; # second line
@rest = ; # everything else• The new-line character is at the end of each line
– can be removed with chomp()
#Eg making wc function of unix in perl #!/usr/local/bin/perl
# wc.pl - imitates unix wc (word count) program
$lines = 0;
$words = 0;
$characters = 0;
while ( <> ) {
$lines++;
@words = split(' ', $_);
$words += scalar(@words);
$characters += length($_);
}
print " $lines $words $characters\n";
Input from a file
Use open function -
open(filehandle, mode, filename);
– returns undef if file cannot be opened
#!/usr/local/bin/perl
# sort.pl - sorts the lines in a file alphabetically
# open a file and assign the filehandle F
open(F, "myfile.txt") or die("can't open myfile.txt: $!\n");
# read in the whole file into an array of lines
@lines = ();
while() {
push(@lines, $_);
}
close(F); # close the filehandle
# sort the lines
@lines = sort @lines; #note that simply using sort @lines won't work, we need new
#array here;
# print out the lines, now sorted
foreach (@lines) {
print; # means the same as print $_;
}
#!/usr/local/bin/perl
# sort.pl - sorts the lines in a file alphabetically
# open a file and assign the filehandle F
open(F, "myfile.txt") or die("can't open myfile.txt: $!\n");
# read in the whole file into an array of lines
@lines = ();
while(<F>) {
push(@lines, $_);
}
close(F); # close the filehandle
# sort the lines
@lines = sort @lines; #note that simply using sort @lines won't work,
#we need new array here;
# print out the lines, now sorted
foreach (@lines) {
print; # means the same as print $_;
}
Writing to file
open(F, ">output.txt")
We add > before file for writing.
# filewrite.pl
open(F, ">output.txt") or die( "cannot write to output.txt : $!\n");
print F "Hello World!\n";
close(F);
Appending
open(F, ">>output.txt");
print F "Goodbye world!\n";
close(F);
File Test Operators
Perl has many operators that you can use to test different aspects of a file. For example, you can use the
-e operator to ensure that a file exists before deleting it. Or you can check that a file can be written to before appending to it. By checking the feasibility of the impending file operation, you can reduce the number of errors that you program will encounter.