Workshop

The workshop provides quiz questions to help you solidify your understanding of the material covered and exercises to give you experience in using what you've learned. Try and understand the quiz and exercise answers before you go on to tomorrow's lesson.

Quiz

1:What's a file handle? What are the STDIN, STDOUT, and STDERR file handles used for?
A1: A file handle is used by Perl to read data from or write data to some source or destination (which could be a file, the keyboard, the screen, a network connection, or another script). The STDIN, STDOUT, and STDERR file handles refer to standard input, standard output, and standard error, respectively. You create file handles to any other files using the open function.
2:What are the differences between creating file handles for reading, writing, or appending?
A2: Use special characters in the filename to be opened to indicate whether that file will be opened for reading, writing, or appending. The default is to open a file for reading.
3:What's the die function used for? Why should you bother using it with open?
A3: The die function exits the script gracefully with a (supposedly) helpful error message. It's most commonly used in conjunction with open because if something so unusual happened that the file couldn't be opened, generally you don't want your script to continue running. Good programming practice says always check your return values for open and call die if it didn't work.
4:How do you read input from a file handle? Describe how input behaves in a scalar context, in a scalar context inside a while loop test, and in a list context.
A4: Read input from a file handle using the input operator <> and the name of the file handle. In scalar context, the input operator reads one line at a time. Inside a while loop, it assigns each line to the $_ variable. In a list context, all the input to end of file is read.
5:How do you send output to a file handle?
A5: Send output to a file handle using the print function and the name of the file handle. Note that there is no comma between the file handle and the thing to print.
6:What do the following file tests test for?
-e
-x
-f
-M
-z

A6: -e test to see if the file exists

-x tests to see if the file is executable (usually only relevant on Unix)

-f tests to see if the file is a plain file (and not a directory, a link or anything else)

-M tests the modification date of the file

-z tests to see if the file exists and is empty

7:What is @ARGV used for? What does it contain?
A7: The @ARGV array variable stores all the arguments and switches the script was called with.
8:What's the difference between getopt and getopts?
A8: The getopt function defines switches with values, and can accept any other options. The getopts declares the possible options for the script and if they have values or not. The other difference is that getopts returns a false value if there were errors processing the command-line switches; getopt doesn't return any useful value.
9:What switches do the following calls to getopts allow?
getopts('xyz:'),
getopts('x:y:z'),
getopts('xXy'),
getopts('xyz'),
getopt('xyz'),
									

A9: getopts('xyz:') allows the switches -x, -y, and -z with a value.

getopts('x:y:z') allows -x and -y, each with values, and -z without a value.

getopts('xXy') allows -x and -X (they are separate switches) and -y, none with values.

getopts('xyz') allows -x, -y and -z, none with values.

getopt('xyz') allows -x, -y and -z, each one with required values, as well as any other single-character switches.

Exercises

1:Write a script that merges two files (specified on the command line) with their lines intertwined (one line from file 1, one line from file 2, another line from file 1, and so on). Write the resulting data to a file called merged.
A1: Here's one answer:
#!/usr/ bin/perl -w
use strict;

my ($file1, $file2) = @ARGV;

open(FILE1, $file1) or die "Can't open $file1: $!
";
open(FILE2, $file2) or die "Can't open $file2: $!
";
open(MERGE,">merged") or die "Can't open merged file: $!
";

my $line1 = <FILE1>;
my $line2 = <FILE2>;
while (defined($line1) || defined($line2)) {
    if (defined($line1)) {
        print MERGE $line1;
        $line1 = <FILE1>;
    }
    if (defined($line2)) {
        print MERGE $line2;
        $line2 = <FILE2>;
    }
}

2:Write a script that merges the two files only if the filename extensions are the same, and use that same filename extension for the final merged file. If the extensions are different, exit the script with an error message. (Hint: use regular expressions to find the filename extensions).
A2: Here's one answer:
#!/usr/bin/perl -w
use strict;

my ($file1, $file2) = @ARGV;
my $ext;
if ($file1 =~ /.(w+)$/) {
    $ext = $1;
    if ($file2 !~ /.$ext$/) {
        die "Extensions do not match.
";
    }
}

open(FILE1, $file1) or die "Can't open $file1: $!
";
open(FILE2, $file2) or die "Can't open $file2: $!
";
open(MERGE,">merged.$ext") or die "Can't open merged file: $!
";

my $line1 = <FILE1>;
my $line2 = <FILE2>;
while (defined($line1) || defined($line2)) {
    if (defined($line1)) {
        print MERGE $line1;
        $line1 = <FILE1>;
    }
    if (defined($line2)) {
        print MERGE $line2;
        $line2 = <FILE2>;
    }
}

3:Write a script that merges two files and takes a single option: -o, which bypasses the error message from the previous exercise and merges the file anyhow (the extension of the final file is up to you).
A3: Here's one answer:
#!/usr/bin/perl -w
use strict;
use Getopt::Std;
use vars qw($opt_o);
getopts('o'),

my ($file1, $file2) = @ARGV;
my $ext;

if ($file1 =~ /.(w+)$/) {
    $ext = $1;
    if ($file2 !~ /.$ext$/) {
        if (!$opt_o) {
            die "Extensions do not match.
";
        }
    }
}

open(FILE1, $file1) or die "Can't open $file1: $!
";
open(FILE2, $file2) or die "Can't open $file2: $!
";
open(MERGE,">merged.$ext") or die "Can't open merged file: $!
";

my $line1 = <FILE1>;
my $line2 = <FILE2>;
while (defined($line1) || defined($line2)) {
    if (defined($line1)) {
        print MERGE $line1;
        $line1 = <FILE1>;
    }
    if (defined($line2)) {
        print MERGE $line2;
        $line2 = <FILE2>;
    }
}

4:Write a script that takes a single-string argument and any of four switches, -u, -s, -r, and -c. -u returns the string in uppercase, -s removes all punctuation and whitespace (s stands for “squash”), -r reverses the string, and -c counts the number of characters. Make sure you can combine the options for different effects.
A4: Here's one way:
#!/usr/bin/perl -w
use strict;
use Getopt::Std;
use vars qw($opt_s $opt_r $opt_u $opt_c);
getopts('sruc'),

my $str = $ARGV[0];

if ($opt_s) {
    $str =~ s/[s.,;:!?'"]//g;
}

if ($opt_r) {
   $str = reverse $str;
}

if ($opt_u) {
   $str = uc $str;
}

if ($opt_c) {
   $str = length $str;
}

print "$str
";

5:BUG BUSTERS: This script is called like this:
myscript.pl -sz inputfile

What's wrong with this script? (Hint: The test for $opt_z will not return true).

use strict;
use Getopt::Std;
use vars qw($opt_s $opt_z);
getopt('sz'),

if ($opt_z) {
   # ...
}
									

A5: The script snippet uses the getopt function. This function (as opposed to getopts, assumes all the switches will have values associated with them. So when the script is called with the switch -sz, getopt assumes that you're using the -s switch, and that its value is z. The -z switch never registers to getopt. Use the getopts function instead to make sure both $opt_s and $opt_z are set.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset