Introduction to "Learning Perl"

Introduction

The examples and comments in this introduction are taken from the Learning Perl book by Randal Schwartz and Tom Christiansen. This introduction was first presented to the Fraser Valley Linux User Group in April 2001.

What is Perl?

Perl was designed to assist the programmer with common tasks that are probably to heavy for shell, but yet too weird or complicated to code in C.

It is great for small short powerful scripts that can be run anywhere. On the other hand, it can be used to write large applications. By using the many modules available on CPAN, applications can be quickly developed by reusing and adapting existing code.

Basic Concepts

Here is “Hello World”:

#!/usr/bin/perl
print (“Hello, World!\n”);

Save this to a file, such as hello.pl. Then, make it executable using the chmod command from the command prompt:

chmod +x hello.pl

To execute this new perl script, just run it from the command line:

kibble:~# ./hello.pl
Hello, World!

On the command line

Now, that was simple. So what does the first line do? The first line, #!/usr/bin/perl, is executed by you current shell. This line basically tells your shell to run perl on the rest of the contents of the file. The print function is built into perl. Like many things in perl, the () brackets are optional. In fact, we don’t even need this file at all. Perl has many handy command line arguments that allow you to pass, for example, code as an argument:

kibble:~# perl -e 'print "Hello, World!\n"';
Hello, World!

That was a rather useless example… here’s something better:

kibble:~# perl -pi -e 's/hello/bye/g' *

This command loops through all the files denoted by the * wildcard, and runs the regular expression /hello/bye/ on them, in place. The end result is all occurrences of hello in any file in the current directory will be replaced with bye. This could be done using cat and sed, but it gets really ugly really fast:

for i in *; do cat $i | sed –e ‘s/hello/bye/g’ > $i.new; mv $i.new $i; done

Eek. Writing a small program in C would just take too long. By the time you’ve thought the problem through, wrote the code, compiled it, and debugged it, you could have gotten the latest scoop at [insert all your favorite Linux news sites here].

Interactive scripts

Here’s some simple usage of variables used in an interactive script:

#!/usr/bin/perl –w
print “What is your name? “;
$name = <STDIN>;
chomp ($name);
print “Hello, $name!\n”;

We’ve changed the first line. The –w flag enables many useful warnings. Use it. Line 3 is doing a lot of things. In one swoop, its sucking the contents of standard input into a variable $name. Perl always sets up STDIN and STDOUT before running your program. Additionally it select()’s them as well, so you don’t have to explicitly print to the filehandle. In this example, <STDIN> is overkill as <> could be used, but <STDIN> makes it easy to keep track of what exactly is being read.

Chomp simply chomps tailing new line characters (\r or \n) off the end of the string.

Arrays

Like everything else, arrays in Perl are much easier to handle then in other languages. The @ symbol is used to tell perl that a variable is going to be an array:

@array = (“foo”, “bar”, “baz”);

That’s your simplest array. There are many ways you can print out the contents of this array. Here’s a method more like the how you would typically do it in C/C++:

# the typical C-like way:
for ($i=0; $i<3; $i++) {
      print $array[$i] , “\n”;
}

# more perlish:
@array = qw(foo bar baz);
foreach $element (@array) {
      print $element, “\n”;
}
# even more perlish:
@array = qw(foo bar baz);
print for (@array);

Hashes

Hashes are kind of like arrays, with values keyed of the index. Unlike the list array, however, elements in the array aren’t referenced by a positive integer (0,1,2,3,...), but by a scaler strings called keys. Elements of a hash have no order. Basically a hash is just a big bag of “things”, and you put things in or take them out based on what you call the “thing”. Hash variables are a %, followed by a letter, then zero or more letters or digits. Here’s some examples of working with hashes:

 # assign some key/value pairs
 $ages{“bob”} = 57.9;
 $ages{‘sue’} = 10.0;
 $ages{joe} = 99; 
 $ages{joe} -= 50;
 
 @keys = keys(%ages); # @keys is now bob, sue, joe
 @all = %ages; # @all is now bob, 57.9, sue,10.0,joe,49
 @backwards = reverse %normal; # swap keys/values
 @ages{“bob”, “sue”, “joe”} = (57.9, 10.0, 99-50); 
 %newages = (‘abe’ => ‘30’, ‘harry’ => 40);
 %ages{keys %newages} = values %newages;
 foreach $person (keys(%ages)) {
       print “$person is $ages{$person} years old.\n”;
 }
 while (($name, $age) = each (%ages)) {
       print “$name is $age years old.\n”;
 }

Given the functions above, you can write concise code that doesn’t waste time keeping track of indexes, array lengths, custom data structures, etc. Hashes and Arrays don’t have to only contain scaler values. A hash can have a value that is hash or an array. An array can have an element that is a hash. Thus, you could make a Hash of Arrays of Hashes of Arrays of Arrays... it would be ugly, but it could be done.

CGI scripts

Let’s jump ahead... how about a guest book CGI?

#!/usr/bin/perl –w
# addcomment.cgi: add a name/email/date/comment to the guestbook 
use CGI;
$query = new CGI;
$name = $query->param(“name”);
$email = $query->param(“email”);
$comment = $query->param(“comment”);
$date = `/bin/date`;

$comment =~ s/\r//g;
$comment =~ s/\n/<br>/g;
open (GUESTBOOK, “>> guestbook.txt”);
print GUESTBOOK “$name | $email | $date | $comment\n”;
close (GUESTBOOK);

print $q->header;
print qq(<html>
<head><title></title></head>
<body>
Thank you for signing the guestbook!
</body>
);

Ok, that was simple... how about printing the contents of the guestbook out?

#!/usr/bin/perl –w
# viewcomment.cgi: view all the guestbook entries
use CGI;
$query = new CGI;

 print $query->header, qq(
 <head><title></title></head>
 <body>
 <h3>Guestbook</h3>
 );
 
 open (GUESTBOOK, “< guestbook.txt”);
 while ($line = (<GUESTBOOK)) {
       chomp ($line);
       my ($name, $email, $date, $comment) = split (‘ | ‘, $line);
       print <<END_ROW;
 Name: $name<br>
 Email: $email<br>
 Date: $date<br>
 $comment
 <hr>
 END_ROW
 }
 close (GUESTBOOK);
print “</body></html>”;

Handy perl modules (all available on CPAN) include: CGI, Net::TCP, Net::DNS, Net::SMTP, MIME::Entity, Bundle::CPAN, PerlVision, XMMS, DBI

Help! There are many sources of information on all things Perl related. Here are some starters.

For help on a particular standard Perl function:

perldoc –f funcname

For help on a perl module:

perldoc Module::Name

To install any perl module from CPAN:

perl –MCPAN –e shell
cpan> i /func_wanted/

Final links