An Introduction to Perl








Course book




Lyle Hopkins



Written by Gareth Hopkins

About the course tutor

Lyle started programming from an early age on a ZX Spectrum this interest in computers continued and with the expansion of computing he has remained at the forefront of programming.

Nine years ago while at college Lyle built a business selling Perl scripts, from a directory listing package to an enquiry handler CRM the most successful product was affiliate software AllAffiliatePro? . Lyle made the decision to focus his attention on developing AllAffiliatePro? and continues to do so using Perl as his preferred language. Now the leader of the Perl chapter for Bristol, Lyle is considered a Perl programming guru, being invited to give lectures at local universities, and becoming actively involved in developing a qualification in the language.

Chapter 1: Getting Started with Perl - Computer set up

Windows:

ActivePerl? can be downloaded from http://www.activestate.com/activeperl/ ensure that you select the right edition for your operating system. The installation should automatically associate .pl files with the Perl interpreter.

Linux:

Perl is included in most distributions of Linux. If you do not have the Perl package installed for your distro there will be one available, you can also download ActivePerl? from the link above.

Setting up a web server

Windows:

If you do not have windows IIS you can download Apache from http://httpd.apache.org/download.cgi

If you download the msi version you'll have a nice wizard to take you through the install. Providing you follow the defaults Apache will be displayed locally at http://localhost .

Linux:

Apache is also already included with most distributions and is available at http://localhost also. You may need to install your distro's package for this.

Chapter 2: Programming and Computers

A basic computer consists of CPU, RAM and a HDD with input devices such as keyboard and mouse, output devices such as VDU and printers.

The CPU processes requests based on the 86 instruction set. Early computers were programmed in binary a series of 0’s and 1’s. 1 byte = 8 bits of binary i.e 01001010. This made programming a lengthy process so assembly language evolved and then on to C programming.

C is the foundation for most programming languages we have today. Higher level languages such as Perl, Java and Python use richer syntax making it easier to code larger more detailed programs. A program that's hundreds of lines of C could be just tens of lines of Perl.

Chapter 3: Programming in Perl

This course is short so it's structured to be as hands on as possible. But before we can write any code, you need to understand a few basics.

Comments

To make the examples clearer we use comment tags. Anything on a line after a #, is a comment and ignored by Perl (this isn't always true).

#This is a comment

Outputting data

At this point we'll cover basic data output using print, so that you can get hands on a writing some working code. The print statement is used in many programming languages as the means of outputting data to a variety of devices, such as your HD in the form of a file, or text onto your screen.

print 'Hello world!';

Line endings

So that long lines of code can be easily broken over several lines, or short lines of code can be put on the same line, lines of Perl code must end with a semi colon ';'. As with comments there are of course exceptions.

Running Perl scripts

Perl scripts are just text files that contain Perl code. They are most commonly saved with the file extension “.pl”. These scripts can be ran along the command line, using the Perl interpreter. Let's use the above print example as our first program. Open a text editor such as notepad, word processors such as Word and WordPad? are not suitable as they try to format the text. Perl scripts should always start with the path to Perl. This is known as the shebang line. In these exercises we'll be invoking Perl directly so it's not technically needed, but it is good practice to put it in anyway.

In your text editor type:-

#!c:/perl/bin/perl.exe

print 'Hello world!';

Save this as hello.pl within a suitable folder (such as “c:\perlscripts”). You'll see that the path to Perl uses forward slashes / as opposed to backslashes \. That is because Perl was originally developed for Unix based systems which use the forward slash for directory paths.

Now open a command prompt (usually Start->Accessories->Command Prompt), navigate to the folder where you saved the hello.pl script (“cd \perlscripts”) and run the script with the Perl interpreter (“perl hello.pl”). You should get the output “Hello World!”.

Variables

Data that you are currently working with is stored in variables. Think of variables as labelled containers. There are different kinds of variables for storing different kinds of data.

For example to define a variable in C you need to declare what type it is e.g.

Number = int

Letter = char

Word = varchar

Luckily Perl's variables aren't as strictly typed.

Scalars

In Perl integers, strings, etc, do not have to be defined separately and are more simply defined as Scalars e.g.

$number = 10;

$char = 'c';

$huge = 'pages of information';

Scalars are denoted by the $ sigil. Perl has variables that can be global; allowing all parts of the program to access them, or local; allowing only certain blocks of code access them.

A global variable is defined as

our $name = 'xyx';

Whereas a local variable is

my $name = 'xyz';

It's good practice to have all or most your variables as local variables.

Scalars that have been initialized but not assigned a value have a special value known as NULL. Perl calls NULL undef, for undefined. undef is not the same as an empty string.

my $scalar; # $scalar will contain undef

my $empty = ''; # $empty will contain an empty string

my $undef = undef; # $undef will contain undef

† The 'our' syntax for defining global variables was introduced with Perl v5.6. Some people still prefer the old method of declaring globals with: use vars qw( $LIST @OF %GLOBALS );

Using Scalars

Let's update our hello.pl script to use a scalar to contain the message:-

#!c:/perl/bin/perl.exe

my $message = 'Hello world!';

print $message;

Working with Scalars

There are different ways of working with Scalars. Perl is well known for TIMTOWTDO (There is more than one way to do it). Here are some examples of common things you'll want to do with Scalars.

Interpolation

Our previous hello.pl example uses single quotes '. Single quotes do not interpolate Scalars. Such that the code

my $name = 'Lyle';

print 'Hello $name';

Would output the text “Hello $name”.

Double quotes do interpolate, such that the same code with double quotes

my $name = 'Lyle';

print “Hello $name”;

Would give you “Hello Lyle”.

Joining strings

Strings can be joined with double quotes, the join function, or by using the dot ' . ' operator.

my $start = 'Hello';

my $end = 'World';

my $joined = “$start $end”; # Same

$joined = join( ' ', $start, $end ); # Same

$joined = $start . ' ' . $end; # Same

Repeating strings

You can also repeat strings with the x operator.

print 'Hi!' x 5;

Would display “Hi!Hi!Hi!Hi!Hi!”.

Working with numbers

You have all the normal math operators. Examples:-

print 1 + 1; # Displays 2

my $multi = 5 * 5; # $multi contains 25

my $div = 5 / 5; # $div contains 1

Arrays

Defined using the @ symbol in front of the array name, arrays store a list variables with numbered locations starting at 0. e.g

my @array = (‘one’, ‘two’);

stores ‘one’ at location 0 and ‘two’ at location 1. This is an important thing to note with a lot of computer arithmetic, numbering generally starts at 0.

To add a variable to the end of any array you can use the push command.

push( @array, ’three’ );

or simply use:

@array = ( @array, ’three’ );

To join an array

my @join = ( @array1, @array2 );

To take an item off the end of an array, use pop.

my $item = pop( @array );

So push and pop are a pair of functions that deal with adding/removing from the end of an array. Their counterparts are unshift and shift, that deal with adding/removing from the start of an array.

shift takes the first item off of an array.

my $item = shift( @array );

and unshift puts it back on

unshift( @array, 'zero' );

To access a value in an array you need to reference its location e.g

my @array = (‘one’, ‘two’,’three’);

my $item = $array[1];

$item will contain 'two', if no value is returned you get undef. Note that when obtaining an arrays value you use $ rather than @ and square brackets []. This is because you are accessing a single Scalar value form the array, not the whole array.

To sort an array

@array = sort @array;

The default sort is an ASCII one, so A-Z goes before a-z. We'll cover more on sorting later.

Getting input from the user

There are different ways of getting input from a user. From command line arguments to sockets. Here are a couple of common methods.

Command line arguments

Perl has a special variable named @ARGV. It's an array containing all of the parameters passed into the script when it's been called from the command line. For instance the script:-


#!c:/perl/bin/perl.exe
print $ARGV[0];

Would print the first parameter passed in. So if called with “perl script.pl Hello” it would display “Hello”. If called with “perl script.pl Hello Lyle” it would still only display “Hello”. This is because it's only printing the first parameter passed. You could use parenthesis to make the first parameter contain both Hello and Lyle, such as 'perl script.pl “Hello Lyle”' would print “Hello Lyle”.

STDIN file handle

STDIN stands for 'Standard Input”. Generally speaking, all Unix derived languages will have a STDIN, STDOUT 'Standard Output' and STDERR 'Standard Error'. They are treated as file handles that you can either read from, or write to. You've already used STDOUT, by default print goes to STDOUT, so the following lines are the same:-


print “Hello”;
print STDOUT “Hello”; # Same

You can read from STDIN using the readline command, although Perl provides shorthand in the form of <FILEHANDLE>, such that:-


my $name = readline(*STDIN);
my $name = <STDIN>; # Same

It's uncommon to use readline, so stick with <STDIN>. You'll notice that in the readline example, STDIN has a * sigil, this is because to pass file handles into functions you must pass the whole GLOB. I'm not covering GLOBs here, for now think of them as another kind of variable.

The example code above will pause the program and wait for user input, once the user hits enter the program will continue and $name will contain whatever they typed.

Conditionals

Things would be pretty boring if programs just went in a straight line all the time. Conditionals allow the software to make decisions based on variables, often ones that have been input. Perl offers if, elsif, else and for convenience unless.

if

The if statement allows you to run a block of code if a condition is true. They are in the format:-

if ( CONDITION ) {

CODE

}#if

You'll notice the use of curly brackets again. This time they surround the block of code that is to be run if the condition is true. The small comment on the end #if is a personal touch and not required. In larger programs you can have many code blocks within code blocks, a simple comment on the end bracket can help you keep track of where they started.

In singular context, Perl sees anything that isn't undef, 0, 0.0 or '' (empty string), '0' (string containing 0) or an empty list as true. Examples:-

if ( 0 ) { } # False

if ( 1 ) { } # True

if ( 0.0 ) { } # False

if ( '' ) { } # False

if ( 'text' ) { } # True

if ( undef ) { } # False

You can also reverse this with not or !, such as:-

if ( ! 0 ) { } # True

if ( not 1 ) { } # False

You can also make comparisons or check if an operation or function returns a true value:-

if ( 0 == 0 ) { } # True

if ( 1 == 0 ) { } # False

Note that for comparisons you need to use == rather than just =. This is because = is used for an assignment. Example:-

# Correct way

my $value = 1;

if ( $value == 1 ) { } # True

# Wrong way

if ( $value = 0 ) { } # True

Both examples return true. This is because the second one assigns 0 to the scalar $value which is a successful operation returning true. !, >, < can also be used:-

if ( 0 = 0 ) { } # False

if ( 1 > 0 ) { } # True

if ( 0 <= 0 ) { } # True

When comparing strings you use the eq and ne syntax instead (equals, not equals respectively):-

if ( 'a' eq 'b' ) { } # False

if ( 'a' ne 'b' ) { } # True

You also have OR, ||, AND, &&. OR and || do basically the same thing, as do AND and &&. There are subtle differences in preference, but I won't be covering them as the vast majority of the time they are interchangeable.

if ( 'a' eq 'b' || 1 > 0 ) { } # True

if ( 'a' ne 'b' && 1 < 0 ) { } # False

else

You may also use the else statement with if, allowing to to do one thing or the other. Such as:-

if ( $name eq 'Lyle' ) {

print 'Thanks for teaching us Lyle';

}#if

else {

print “Hello $name”;

}#else

elsif

Often 'else if' or 'elseif' in other languages, shortened to elsif in Perl. It allows you to run another condition only if the original if is false. You can have many elsif statements as you want, often you end with a else. Such as:-

if ( $name eq 'Lyle' ) {

print 'Thanks for teaching us Lyle';

}#if

elsif ( $name eq '' ) {

print “Please input your name”;

}#elsif

else {

print “Hello $name”;

}#else

unless

For general convenience and to make things read easier, unless is provided as an alternative to if not.

if ( not( 9 > 10 ) ) { } # True

unless ( 9 > 10 ) { } # Same

Random numbers

Random numbers can be useful for many things. Later we'll use this to create a basic guessing game. Perl has the rand function, that returns a random decimal number between 0 and the number you give it. For example:-

print rand(10); 

Will typically display a number between 0 and 9.999999999999999. A lot of the time you'll be interested in whole numbers (integers). The int function returns only the integer portion of a whole number. So the previous example can be updated to:-

print int( rand(10) ); 

Which will now display between 0 and 9.

Hashs

A Hash is an associative array with key and value pairs. It's defined using the % sigil. E.g.

my %dogs = ( bolt => 'male', cassie => 'female' );

my $sex = $dogs{'cassie'}; # returns the value 'female'

Note that as with arrays, when you are accessing a single value you use $ rather than %, but with hashes you use curly brackets {}.

To add a single key/value pair to a hash you do:-

$dogs{'barley'} = 'female';

When working with hashes you have three useful functions: keys, values and delete. keys returns a list of the hash's keys:-

my @keylist = keys %dogs; # @keylist would contain 'bolt', 'cassie' & 'barley'

Remember that an array is a list of values, so keys returning a list of the hash's keys is effectively an array. You can in fact use keys wherever you'd normally use an array, such as in for and foreach loops that we cover later. values works in a similar way, but returns a list of the hash's values.

my @valuelist = values %dogs; # 'male', 'female', 'female'

An important thing to note is that while arrays are in a fixed order, hashes are not. So the order in which keys and values return will not be the same in which you put in. The above example could also return 'female', 'male', 'female' or 'female', 'female', 'male'. In programming terms this is often referred to as a bag (jumbled) instead of a list (ordered).

delete lets you remove a key/value pair from the hash:-

delete $dogs{'barley'};

Loops

Loops allow you to repeat pieces of code over and over, usually until a variable has a certain value, or the user gives certain input. Perl has several looping constructs, most commonly for / foreach, while, until.

for/foreach

for and foreach are interchangeable and work in exactly the same way. Many Perl programmers prefer foreach for things like looping through an array, simply because it reads better. Personally I use for when it's a classical for loop counting up an integer, such as:-

for ( my $int = 0; $int < 10; $int++ ) {

# CODE

}#for

I use foreach for arrays, which includes the lists returned by keys and values.

foreach my $key ( keys %hash ) {

print “$key = $hash{$key}\n”;

}#foreach

Will print the key and hash value from the above example.

foreach my $elem ( @array ) {

print “$elem\n”;

}#foreach

Will display all the elements of the array.

while

while loops use a condition just like if statements do. The block of code will be repeated while the condition is true.

while ( 1 ) {

# infinite loop

}#while

until

The counterpart to while is until. The code block will be run until the condition is true.

my $i = 1;

until ( $i > 10 ) {

print “$i\n”;

$i++;

}#until

That example would display 1 to 10.

Task

A) Make a random number guessing game. The user has to pick a number between 1 and 20. If they pick to high it tells them 'higher', if they pick to low it tells them 'lower'. They only get 5 tries.

B) Extend the previous task to take the players name and use it in the dialogue.

C) Extend the previous task to give the player a score.

D) Extend the previous task to add new features of your own and make it more entertaining.

Task Solution

There are many different ways you can code a solution to the task. Here is an example with the steps I took to create it.

1. Prepare the file

Start the file and add comment tags for the objective


#!/perl/bin/perl.exe

# Make a random number guessing game.

# The user has to pick a number between 1 and 20.

# If they pick to high it tells them 'higher'

# If they pick to low it tells them 'lower'.

# They only get 5 tries.

Having the objectives at the top of the file helps you keep focus on what you are aiming to achieve.

2. Think out the logical steps and them as comments

It makes it a lot clearer what you are doing.


#!/perl/bin/perl.exe

# Make a random number guessing game.

# The user has to pick a number between 1 and 20.

# If they pick to high it tells them 'higher'

# If they pick to low it tells them 'lower'.

# They only get 5 tries.

# Introduce the game
# Generate a random number

# loop a maximum of 5 times
# request user guess
# Check if guess correct
# Check if guess higher
# Check if guess lower

3. Create the code

Add the actual working code between the comment tags


#!/perl/bin/perl.exe

# Make a random number guessing game.

# The user has to pick a number between 1 and 20.

# If they pick to high it tells them 'higher'

# If they pick to low it tells them 'lower'.

# They only get 5 tries.

# Introduce the game
print “Welcome to the number guessing game\n\n”;

# Generate a random number
my $number = int( rand( 20 ) );
$number++;

# loop a maximum of 5 times
my $tries = 5;
while ( $tries > 0 ) {

# request user guess
print “Guess the number between 1 and 20. $tries guesses remaining:\n”;
my $guess = <STDIN>;

# Check if guess correct
if ( $guess = $number ) {
print “Well done you guessed correct!\n”;
$tries = 0;
}#if

# Check if guess higher
if ( $guess > $number ) {
print “Lower\n”;
}#if

# Check if guess lower
if ( $guess < $number ) {
print “Higher\n”;
}#if

$tries--;
if ( $tries =
0 ) {
print “No guesses left!\n”;
}#if

}#while

Quotes

We've already covered single and double quotes. Let's go into more detail. For instance what if you are quoting text that has quotes in them? Perl treats \ as a special character, it's used as an 'escape character'. This means it can take away the functionality of other special characters such as $. It also adds special functionality to normal characters.


print “\$money”; # prints $money instead of the contents of $money
print 'It's all good'; # ERROR
print 'It\'s all good'; # Correct
print “\n”; # prints a new line
print '\n'; # prints \n
print “\t”; # prints a tab character
print “\\”; # prints a single \

You'll notice that \ doesn't add functionality when used within single quotes, but it still acts as an escape character. If you want a \ then you do two \\. The most common combinations you'll use are \n for newline, \r for carriage return and \t for tab.

Quick quotes

Sometimes using either “ or ' can be painful. For example:-


print “Lyle said \”Sometimes it's annoying\””;
print 'Lyle said ”Sometimes it\'s annoying”';

You need to use \ to escape no matter which quotes are used. For times like this quick quotes are perfect. q acts like single quotes, qq like double.


print qq~Lyle said ”Sometimes it's annoying”~;
print q~No interpolation $now~; # prints No interpolation $now

You can choose which character is used to surround the string. I tend to use ~ as it doesn't come up often in regular strings. There is also a quick quote for dealing with lists, qw.


my @array = ( 'list, 'of', 'elements' );
my @array = qw( list of elements );

It saves you having to type out the list with commas and speech marks.

Reading from the Environment

Perl provides a special hash variable called %ENV that contains information about the environment your program is being run in. It's straight forward to print out the contents of %ENV in a foreach loop:-


foreach my $key ( keys %ENV ) {
print “$key = $ENV{$key}\n”;
}#foreach

%ENV is particularly useful when you are writing CGI scripts as you can get information such as browser Cookies and the users IP address.

Subroutines

When your program starts to get large, the need to break it down into subroutines becomes apparent. If you find yourself about to write the same or similar blocks of code then these belong in subroutines.


sub NAME {
BLOCK
}#sub

For example, we could expand the previous random number guessing game script to include other games. We could put each of these into a subroutine and have the user choose which game to play.


print “Select game to play:\n1) Number game\n2) Adventure game\n3) Exit\n”;
my $input = <STDIN>;
if ( $input = 1 ) {
number_game();
}#if
elsif ( $input =
2 ) {
adventure_game();
}#elsif
else {
exit;
}#else

sub number_game {
# Game code
}#sub

sub adventure_game {
# Game code
}#sub

This allows us to structure our code better, the conditionals are short and clear at the top of the script, whereas the code for the games are grouped in subroutines lower down.

Custom Functions

Perl uses the same subroutine syntax for creating functions. The special variable @_ contains all passed in parameters and you return data with the return function.


sub NAME {
my ( $param1, $param2 ) = @_;
BLOCK
return $value;
}#sub

So a simple function that checked an array for a certain string:-


sub check_array {
my ( $string, @array ) = @_;
my $found = 0;
foreach my $item ( @array ) {
$found = 1 if ( $item eq $string );
}#foreach
return $found;
}#sub
my $exists = check_array( 'string', @array );

Teaching yourself more

Online

Perl Mongers – www.pm.org, you local group is Bristol and Bath Perl Mongers, ran by Lyle Hopkins. http://perl.bristolbath.org

PerlMonks?www.perlmonks.org, you need to understand HTML in order to post, but a very useful resource if you get stuck.

Perldoc – perldoc.perl.org, online documentation for Perl commands and syntax

CPAN – Comprehensive Perl Archive Network, large collection of ready to use Perl modules for just about everything.

PerlTrain? follow on course – Heavily discounted follow on course for suitable students.

Recommended Reading

Perl Programming 3rd Edition, July 2000, Larry Wall, Tom Christiansen and Jon Orwant published by O'Reilly

Learning Perl

CGI Programming with perl 2nd Edition, July 2000, Scott Guelich, Shishir Gundavaram and Gunther Birznieks published by O'Reilly

Topic revision: r3 - 09 Aug 2010 - 10:32:24 - LyleHopkins
 
This site is powered by the TWiki collaboration platformCopyright &© by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback