Vous êtes sur la page 1sur 33

LESSION 1

I'll try to explain things as much as possible, so whether you are


familiar to programming or not, you should find it easy to learn Perl
and be comfortable with using this language after the end of this
series of articles.History of Perl

Larry Wall created a scripting language in 1987, which he called the


"Practical Extraction and Report Language". It was designed as a
text-processing language for Unix operating systems. Various tools
and languages already existed (Unix shells, sed, awk, C...etc) and
programmers usually used many of them together. Larry Wall wanted
the language to cover all aspects and needs related to text-
processing so the programmer wouldn't have to use any other tool in
conjunction with Perl. Also, he designed Perl as a language that was
easy and fast to use but which would also allow the programmer to
get into the innards of things.

Perl offered features no other language had offered before. It was


filling a niche no other tool had, and it immediately became popular.
In 1994, Perl 5 was released and at that stage it was a stable and well
established general purpose programming language.

Particularities of Perl

Perl is truly unique. As we go along and study its different features


you'll probably see that by yourself. Larry Wall applied a lot of his
linguistic knowledge into the making of Perl. Some people even
consider it a natural language. Its vocabulary is extremely rich and its
grammar is very flexible. Perl programmers usually say "There's more
than one way to do it". In fact, you can literally write a Perl script your
way, with your own style. Some people even do "poetry" in Perl :)
Because of this, some Perl scripts can be very difficult to read.
Writing them though, is always a pleasure.

The Perl interpreter


Perl is an interpreted language. This means that the code you will
write using the Perl language will need a program called the Perl
interpreter in order to be run. For instance, if you write a Perl script in
a file called myScript.pl (.pl is commonly used as an extension for Perl
scripts), you will not be able to run it directly. You will need to call the
interpreter to run it:

perl myScript.pl

In this example

myScript.pl is your Perl script and perl is the Perl


interpreter. Installation of the Perl interpreter

The Perl interpreter is an essential tool and it is usuallyinstalled by


default on most GNU/Linux distributions. Forinstance, the following
distributions come with a recent and updatedversion of Perl:

Suse 10.1

Fedora Core 5

Debian Testing

Ubuntu 5.10

Mandriva 2006

Slackware 10.2

Mepis 3.4-3

Gentoo 2006.0

Knoppix 5.0

For an exhaustive list of distributions which include perl, you can


search distrowatch.com: http://distrowatch.com/search.php?
pkg=perl&pkgver=5.8.8#pkgsearch

To makesure the interpreter is installed on your machine and to see


which version it is, you can open a terminal and type:

perl -v

If it is installed, this should print the version of Perl installed on your


machine:

clem@pluto:~> perl -vThis is perl, v5.8.8 built for i586-linux-thread-


multiCopyright 1987-2006, Larry WallPerl may be copied only under
the terms of either the Artistic License or theGNU General Public
License, which may be found in the Perl 5 source kit.Complete
documentation for Perl, including FAQ lists, should be found onthis
system using "man perl" or "perldoc perl". If you have access to
theInternet, point your browser at http://www.perl.org/, the Perl Home
Page.

If Perl is not installed on your system, you will certainly be able


to install it through your distribution's package manager. Simply
search for perl within your distribution's repositories, or start
considering using another distribution. After all, Perl is an essential
tool which should be included by default and regularly updated by
your distribution: http://www.cpan.org/ports/#linux

Implicit use of the interpreter

The Perl interpreter is usually used to run Perl scripts which are
written in a file. It also features an interactive mode which you can
use by simply typing perl without any argument. However, in this
lesson we will focus on using files.
In order to run a Perl script, you can call the interpreter with the file
as an argument:

perl myScript.pl

... or you can tell the Perl script where to find the interpreter and
make the script executable. This is common practice among
programmers and you are encouraged to do so. Within the script file,
the first line tells the shell how to interpret the file. This line basically
shows the path to the Perl interpreter:

#!/usr/bin/perl

Note: The Perl interpreter is usually installed in /usr/bin, but your


system might be different. To make sure, type "which perl":

clem@pluto:~> which perl/usr/bin/perl

Also make sure your Perl scripts are executable and have proper
permissions:

chmod a+rx myScript.pl

Once the script is executable, it can be run directly. The shell looks at
the first line of the file which starts with #!, and then it runs the
interpreter which path is found on that line with the rest of the file. In
other words, thanks to that little trick, you can run you Perl script
directly:
./myScript.pl

Although you are not explicitly calling the interpreter here, keep in
mind that it is actually run by the shell on your behalf and that it is the
interpreter which runs your script.

Your very first Perl script!

You have your interpreter installed, and you're ready for your first
script: a simple script that writes "Hello World!" on the screen (I
know.. it's a bit useless, but it's more or less a tradition when you're
learning a new programming language, so let's simply write "Hello
World" and enjoy the lesson since it's still easy to understand :)).

Create a file called helloWorld.pl and write the following into it:

#!/usr/bin/perlprint "Hello World! n";

Make the script executable:

chmod a+rx helloWorld.pl

Run the script:

./helloWorld.pl

As you probably expected, "Hello World!" gets printed on the screen.


The script only contains two lines and is quite easy to understand.
The first line will always be the same; it tells your shell where to find
the Perl interpreter. The second line is actually the only Perl
instruction of your script, it tells the interpreter to print "Hello World!"
on the screen. In Perl, each instruction finishes with a semicolon. If
you're new to programming you'll probably forget semicolons in your
code, so be careful with that. The reason for the semicolon is that an
instruction can sometimes be long and take more than one line, so it
is an effective way to mark the end of an instruction. Most languages
use semicolons and once you're used to it, it seems very natural. You
might also wonder what the "n" is for. It simply is a special character
which corresponds to the new line character (as when someone
presses the Enter key) so that the cursor goes the next line of the
screen after printing "Hello World!".

In the next lesson we'll start using variables, opening files and do a
lot of things which will come handy for you later. Now that you know
what Perl is and how to use it, we'll start to focus on the language
itself. Of course, in the meantime I'll be glad to answer your
questions.
LESSION 2

In the previous lesson we learnt what Perl was and how to use the interpreter to run Perl scripts. We also wrote our first Perl
script: HelloWorld.pl. In this lesson we will learn how to use variables and command line arguments. We will then use them in
order to write our second Perl script: a calculator!

Learning Perl - Lesson 1

What are variables?


Variables are used in every computer language. If you are new to programming, remember the
variables used in algebra equations. For instance, consider the following equation:

a + 5 = 7

In this equation, there is only one variable. Its name is "a" and its value is "2". Variables always
have a name and they always have a value. In algebra their value is usually a number. In
programming, their value can be a number, a character, a string (which means a sequence of
characters), or even a complex object such as an array, a hashtable, a data structure, etc...
Throughout the lessons we will use variables to store many different types of objects or values
and you will become more familiar with the different data types that a variable can represent.

Variables in Perl
In Perl, there a three types of variables: * scalar variables, * arrays, * hashtables.

Scalar variables store a single value. In Perl, scalar variables names are always prefixed with a
dollar sign. For instance:

$a = 2;
$message = "Hello World!";
Arrays can store many values. In Perl, arrays are always prefixed with an at-sign. For instance:

@colors = ("red", "green", "blue");@primaryNumbers = (1, 2, 3, 5, 7);

Hashtables are a special kind of array: associative arrays. They are like arrays, but for each of
the value they store, they also store a corresponding name or label. They consist of pairs of
elements - a key and a data value. In Perl, hashtables are always prefixed with a percent sign.
For instance:

%phoneNumbers = (Alicia => "090-64-773315", Tom => "085-153-


3214", Jimmy => "085-285-4545");

In this lesson we will focus on scalar variables and arrays. They are simple to use and they will
help us write our calculator.

What are command line arguments?


In the previous lesson we first called our script by invoking the Perl interpreter:

perl myScript.pl

Then we saw how to make an implicit call to the interpreter so that the script could be called
directly:

./myScript.pl

Whether we call the interpreter implicitly or explicitly, we can give arguments to the script.
These arguments are given while calling the script, and simply put after the script name:

./myScript.pl argument1 argument2 argument3

For instance, instead of having a script which writes "Hello World!" on the screen, and thus
doesn't need any argument, we will write a calculator in this lesson. Our calculator will calculate
the result of a simple equation which we will give as a command line argument. For instance, if
we wanted our calculator to add 5 and 6, we would call it like this:

./calculator.pl 5 + 6

In this example, we gave three command line arguments:

+
6

The Perl script will have to look at these arguments, identify the second argument to know
what operation to do with the first and third arguments, calculate and print the result on the
screen. Command line arguments in PerlWhen the interpreter runs the Perl script it stores the
command line arguments in an array called @ARGV. Note that the Perl language is case-
sensitive, so it is important to use capital letters here. @ARGV is an array, and like every array
in Perl you can do the following on it:

Get the first element of the array by typing $ARGV[0] (note that as this is a single value
it is represented by a scalar variable and prefixed with a dollar sign).

Get the second elements of the array by typing $ARGV[1]... etc.

Get the index of the last element in the array by typing $#ARGV.

Note that arrays always start from 0, not from 1. Therefore the first element of an array, is
element 0, not element 1. For instance element number 12 corresponds to the 13th element of an
array. This is a convention in many programming languages. The index of the last element in the
array corresponds to the number of elements - 1.

In our example, we call our calculator by giving it three arguments:

./calculator.pl 5 + 6

Therefore we can expect the @ARGV array to contain three elements, $#ARGV being equal to
2 and $ARGV[0], $ARGV[1] and $ARGV[2] respectively being equal to 5, "+" and 6.

Your second Perl script, the Calculator!


You nearly know everything you need in order to code your second Perl script and to write a
nice calculator. In fact you could do it yourself now! As we said before, there are more than one
way to do something in Perl. Try to program the calculator by yourself, and then have a look at
the solution below.

Create a file called calculator.pl and write the following into it:

#!/usr/bin/perl$nbArguments = $#ARGV + 1;print "number of arguments:


$nbArgumentsn";exit(1) unless $nbArguments == 3;$a = $ARGV[0];$b = $ARGV[2];
$operation = $ARGV[1];if ($operation eq "+") { $result = $a +
$b;}elsif ($operation eq "-") { $result = $a - $b;}elsif ($operation
eq "/") { $result = $a / $b;}elsif ($operation eq "x")
{ $result = $a * $b;}print "$a $operation $b = $resultn";
Make the script executable:

chmod a+rx calculator.pl

Run the script :

./calculator.pl 5 + 6./calculator.pl 11 - 2./calculator.pl 4 x


3./calculator.pl 33 / 3

The script works as expected, but there probably are a lot of instructions you didn't fully
understand within this script. So let's look at them.

The first line tells where to find the interpreter, so that we can call the script directly.

The second line takes the index of the last element from the @ARGV array and adds 1 to it.
That way it gets the number of command line arguments given to the script and stores it in a
variable called $nbArguments.

The third instruction simply prints the number of arguments on the screen.

There is a lot to say about the fourth instruction (exit(1) unless $nbArguments == 3;):

"exit" is a Perl function which makes the script stop and return a given code to the shell.
In this example the script stops and returns 1 to the shell. 1 is a Unix convention which
means that there was an error.

"unless" is the opposite of "if". These are Perl statements. In this example, "exit" is
called unless the following statement is true "$nbArguments == 3".

In Perl, and in many programming languages, the equal sign is used to affect values to
variables. For instance, when we wrote $nbArguments = $#ARGV + 1, we assigned a
value to $nbArguments. The double equal sign "==" is a comparison operator which
returns true or false depending on the fact that the variables or values on both side are
equal or not. Perl also provides another operator "eq" which compares strings. Try to use
"eq" for string comparisons and "==" for numbers. Remember that the "=" sign assigns
values and is not a comparison operator.

In brief, (exit(1) unless $nbArguments == 3;) means that the script will stop unless three
command line arguments were given.

The three next instructions simply assign the three command line arguments to variables. We
stored the first one in $a, the third one in $b and the second on in $operation.

Then, depending on the value of $operation, we made a different calculation with $a and $b and
stored the result in a variable called $result. Note that we used "if" and "elsif" statements. We
will come back to these statements later, but for the moment remember that "elsif" is a
contraction for "else if...". Also, note that we used brackets to clearly identify blocks of code
between the if statements and that we indented our code. In general, unless you have a very
simple one liner to write, use brackets for each if statement and always indent your scripts.

The last instruction writes a summary of the operation and its operands as well as the result on
the screen.

In this lesson we learnt how to use variables and command line arguments. We also had a quick
look at If statements, comparisons operator and a few operations. In the next lesson, we'll
manipulate text files and go a bit further in using operators and other statements.

LESSION 3

In the previous lesson we learnt what variables were and how to use command line arguments in Perl. We also wrote our
second Perl script: the Calculator. In this lesson we will learn how to use If statements and loops and how to open files to read
and write into them.

What are If statements and loops?


Every Perl script is made of instructions which tell theinterpreter what to do. Depending on the
purpose of the script you'llwrite different instructions. Sometimes, you might want
someinstructions to be executed only on certain conditions. To do this,you'll use If statements. A
typical If statement is aninstruction which defines three elements:

A condition
A set of instruction to execute if the condition is met

A set of instruction to execute if the condition is not met

For instance,consider the following code:

if ($time > 12){


print "Good Afternoon";
}
else {
print"Good Morning";
}

In this Ifstatement, the condition is ($time > 12). If the condition is metthen the script prints
"Good afternoon", otherwise itprints "Good morning".

Sometimes, you might wantsome instructions to be executed more than once. For this you can
useloops. A typical loop is composed of a condition and a set ofinstructions to execute. There
are different kinds of loops and wewill study them in the chapters below.

If statements in Perl
Perl is a very flexible language and this is particularly truewhen it comes to If statements.

Simple If-statements
The most common form of If statement in programming is composed ofa condition (between
parenthesis) followed by a set of instructionswhich are placed between brackets. For instance:

if ($time > 12) {


print "time is $timen";
print"Good Afternoonn";
}

Although it is considered bad practice, you don't have towrite the brackets if there is only one
instruction in the Ifstatement:

if ($time > 12)


print "Good Afternoonn";

To avoid any possible confusion, it is recommended to always writethe brackets, or, if there is
only one simple instruction to placethe condition and the instruction on the same line:
if($time > 12) print "Good Afternoonn";

In Perl, you can also write the condition after the instructionitself. For instance:

print "Good Afternoonn" if($time > 12);

Else and Elsif Statements

Similarly, you can define an else block of instructions,which will be executed if the
condition is not met:

print"time is $timen";
if ($time > 12) {
print "GoodAfternoonn";
}
else {
print "Good Morningn";
}

Sometimeyoumaywanttodosomethingdependingonmorethanone
condition.OfcourseyoucanalwaysdefineIfstatementwithin
others,butyoucanalsouseelsif,asacontractionofelse,
if(somethingelse..):

if ($time < 12) {


print "GoodMorningn";
}
elsif ($time < 20) {
print "Good Afternoonn";
}
elsif ($time < 23) {
print "Good Eveningn";
}
else {
print "Good nightn";
}

Unless-statements

InPerl,youcanusetheUnlessstatement.Itbehavesexactly
liketheIfstatementbutexecutesthecodeiftheconditionis
notmet.ForinstancethefollowingcodeprintsGoodnightif
it'smorethan11pm:
print "Good nightn" unless($time < 11pm);

Loops in Perl
There are many different kinds of loop in Perl. Here are the mostcommon types.

While loop

This loop executes a block of code while a condition remains true.For instance, the following
code prints Hello three times:

$i = 0;
while ($i < 3) {
print "Hellon";
$i = $i + 1;
}

Until loop

This loop executes a block of code until a condition becomes true.For instance, the following
code prints Hello three times:

$i = 1;
until ($i > 3) {
print "Hellon";
$i = $i + 1;
}

For loop

The for loop is composed of four elements:

A starting assignment

A condition

An incrementation

A set of instructions

The notation of the For-loop is as follows:

for (starting assignment; condition; incrementation) {


instructions
}

The for loop starts by executing the starting assignment. Then,while the condition is met, it
keeps executing the instructions andthe incrementation. For instance the following For-loop
printsHello three times:

for ($i = 0; $i < 3; $i = $i + 1) {


print "Hellon";
}

Note that the ++ operator is usually used to increment a variable,so we could have written $i+
+ instead of $i = $i + 1;

In Perl, you can also use the For-loop with a range operator.The notation for the range
operator is ... For instance, thefollowing code prints Hello three times:

for (1..3) {
print "Hellon";
}

Foreach loop

The foreach loop is used to iterate through the elements of anarray. For instance, the following
code prints the days of the week:

@days = ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday",


"Sunday");
foreach $dayOfTheWeek (@days) {
print "$dayOfTheWeekn";
}

You can also use the foreach loop to iterate through the keys of anhashtable. For instance, the
following code prints the days of theweek:

%days = ();
$days{"Monday"} = 1;
$days{"Tuesday"} = 2;
$days{"Wednesday"} = 3;
$days{"Thursday"} = 4;
$days{"Friday"} = 5;
$days{"Saturday"} = 6;
$days{"Sunday"} = 7;

foreach $day (keys %days) {


print "$day is the day number $days{$day} of the weekn";
}

File Handling
The Perl language was designed to make file handling easy andefficient, so you'll probably
won't have any problem opening filesand reading them.

Opening and closing files

In order to open a file, you'll use the open instructionwhich takes two arguments: the name
of a filehandle and the name ofthe file itself. The filehandle is like a variable which
representsthe handling of the file within the script. For instance, in thefollowing code we're
opening the file clients.txt with afilehandle called CLIENTS:

open (CLIENTS, "clients.txt");

By default, the file is open in read-mode, which means you canonly read from it. You can
decide to open a file in write-mode, inorder to be able to write into it. If the file already existed
or hadsome data written into it, the data will be lost. To open a file inwrite-mode simply add a
> in front of the file name:

open (CLIENTS, ">clients.txt");

If you'd rather keep the data written in the file, you can openthe file in append-mode. This way,
the data will be kept, and whatyou'll write in the file will be appended to it. In order to do
thisadd a >> in front of the file name:

open (CLIENTS, ">>clients.txt");

The open instruction returns true if it managed to open thefile, false otherwise. You can use
this value in order to test thesuccess of the operation. For instance, the following code opens
thefile in write-mode and prints Insufficient privileges if thescript doesn't manage to do so.

open (CLIENTS, ">clients.txt") or print


"Insufficientprivilegesn";

Remember to always close the files once you're finished with them.If you don't your changes
might be lost. In order to close a file,simply use the close instruction on the filehandle:

close (CLIENTS);
Writing into files

Once the file is open in write mode you can write into it simplyby writing into its filehandle.
The print instruction writesthings on the screen by default, but you can specify a filehandle
towrite into. For instance, the following code adds a line Mr JohnDoe in the end of the
clients.txt file:

open (CLIENTS, ">>clients.txt") or die


"Insufficientprivilegesn";
print CLIENTS "Mr John Doen";
close (CLIENTS);

Reading data from files

There are many ways to read the content of a file. Here are thetwo most common ways in Perl.

Copying the content of the file into an array

You can copy the whole content of the file into an array. Eachline will then correspond to an
element of the array. Here is anexample:
open(CLIENTS, "clients.txt");
@lines = ;
close(CLIENTS);
print @lines;
Looping through the filehandle

Alternatively you can loop through the filehandle in a while loopby writing while($line = )
(think of it as whilethere are lines in the clients file, I'm assigning the current lineto $line):

open (CLIENTS, "clients.txt");


while ($line = ) {
print $line;
}
close (CLIENTS);

As you can see, Perl makes it very easy to manipulate files. Inthe next lesson we'll look at how
to search for a particular elementwithin a file, and how to handle and manipulate strings.
LESSION 4

In the previouslesson we learnt about If statements and loops. We also started tostudy how to open files and how to write and
read into them. In thislesson we will learn how to compare strings and we will study someadvanced techniques for parsing files.
String comparisons
The =~ operator

Perl provides an operator which you'll find very useful to parseand search files: "=~". If you are
not familiar with thisoperator, think of it as a "contains" operator. Forinstance:

"helloworld" =~ "world" returns true, as "helloworld" contains "world".


"helloworld" =~ "o worl" also returns true since "oworl" is included in the string
"hello world".
"helloworld" =~ "wrld" returns false because thestring "hello world" does not contain
"wrld".

Using the =~ operator you can easily testif a variable contains a particular string, and this will
help you alot while parsing text files. You can also use regular expressions inconjonction with
the =~ operator. Although it is too early at thisstage to study regular expressions in details, here
are sometechniques that you can use with =~.

We replace the doublequotes by forward slashes in order to tell our =~ operator that we'renot
simply looking for a string anymore but for a matching pattern(with a bit of logic inside it):

"helloworld" =~ "world"is the same as "helloworld" =~ /world/

Although"world" represents a string and /world/ represents anexpression, these two instructions
return true. By adding logic tothe expression, we can refine the meaning of our =~ operator.
=~/^Starts with/

A leading ^ sign changes the meaning of the operator from"contains" to "starts with":

"helloworld" =~ /world/ returns true because "hello world"contains "world".


"helloworld" =~ /^world/ returns false since "hello world"doesn't start with "world".
"helloworld" =~ /^hell/returns true because "hello world" starts with"hell".

=~ /Ends with$/

By adding a $ sign in the end of the expression you can change themeaning of the operator from
"contains" to "endswith":

"hello world"=~ /world/ returns true because "hello world"contains "world".


"helloworld" =~ /world$/ also returns true, but this time it'sbecause "hello world"
ends with "world".
"helloworld" =~ /hello$/ returns false, because "helloworld" doesn't end with
"hello".
The eq and ne operators

You can use both the ^ and $ signsin the same expression, and it would mean that you're looking
for astring with which your variable would both starts and end. Forinstance:

"hello world"=~ /^hello world$/ returns true because "hello world"starts and ends
with "hello world".
"helloworld" =~ /^hello$/ returns false, because although"hello world" starts with
"hello" it doesn't endwith it..

Note that there is no much point using both ^ and $in the same expression. If you're string starts
and ends withsomething it is likely to be equal to that something... if you wantto test the
equality of two strings, you can simply use the eqoperator:

"hello world"eq "hello world" returns true because the twostrings are identical.
The ne operator tests the non-equalityof two strings. It returns true if the strings are different
andfalse otherwise:
"helloworld" ne "good night" returns true.
"helloworld" ne "Hello worlD"returns true (remember that Perlis case-sensitive)
"helloworld" ne "hello world" returns false because bothstrings are the same.
Remember to use the eq and ne operatorsto test the equality of strings in Perl, and their
equivalence == and!= to test numerical values.
The !~ operator

The !~ operator is used as a does not contain operator. What!= is to ==, ne is to eq and !~ is
to =~. For instance:

"hello world" !~ "world"returns false because hello world does contain


world.

"hello world" !~ "wwt"returns true because hello world does not contain
wwt.

Case insensitive search

When you use the =~ operator you test the matching of a stringwithin another, this is always
case sensitive. For instance:

"hello world" =~ "world"returns true.

"hello world" =~ "woRld"returns false.

If you want to make the =~ operator insensitive, add an iafter the expression:
"hello world" =~ /world/ireturns true.

"hello world" =~ /woRld/ialso returns true.

Substitutions

The =~ operator can also be used to find occurrences of a stringwithin a variable and substitute
them with another string. Forinstance, if you have a variable which contains text, and you want
tochange all occurrences of aaa with aab within that text,you can simply use the
following substitution:

$variable =~ s/aaa/aab/;

All occurrences of aaa within $variable will then be changedto aab. Note that we
prefixed our expression with an s tochange the meaning of the operator from contains
tosubstitute.

Parsing files

There are many ways to parse a text file. In Perl, if the file hasits data organized line by line
with delimiters, it is very easy toparse it.

Let's study a simple example. We have a set of employees in a filecalled employees.txt. In this
file, each line represents an employee.The information relative to each employee is delimited
with tabs, thefirst column is the name of the employee, the second column indicateshis
department and the third one his salary. Here is an overview ofthe file:

Mr John Doe R&D 21000


Miss Gloria Dunne HR 23000
Mr Jack Stevens HR 45000
Mrs Julie Fay R&D 30000
Mr Patrick Reed R&D 33000

In order to obtain some statistics, the HR department wants toestablish a list of all male
employees who work in the R&Ddepartment and which salary is more than 25000.

To obtain this list, we design a simple Perl script, which:

1. opens the employees.txt file

2. loops through each line


3. identifies the name, department and salary of the employee

4. ignores and goes to the next line if the employee is female (the name does not start with
Mr)

5. ignores and goes to the next line if the salary is less or equal to 25000.

6. ignores and goes to the next line if the department is not R&D.

7. prints the name and the salary of the employee on the screen.

To do this, we'll introduce two Perl functions:

chomp is used to remove the carriage return found in the end of the line. For
instance chomp $variable removes all carriage returns in the variable.

split is used to cut the line in different parts where it finds a delimiter. For instance
split /o/, hello world returns an array containing hell, w and rld. In
our example we'll split the lines with the tab delimiter, which in Perl is written t.

Here is the script which establishes the list of male employeesfrom the R&D department with a
salary greater than 25000. To makethings a bit clearer, comments were introduced within the
scripts(comments in Perl start with a # sign):

#open the employeesfile


open (EMPLOYEES,"employees.txt");

#for each line


while ($line =) {

#remove thecarriage return


chomp $line;

#split the linebetween tabs


#and get thedifferent elements
($name,$department, $salary) = split /t/, $line;

#go to the nextline unless the name starts with "Mr "
next unless$name =~ /^Mr /;

#go to the nextline unless the salary is more than 25000.


next unless$salary > 25000;

#go to the nextline unless the department is R&D.


next unless$department eq "R&D";

#since allemployees here are male,


#remove theparticle in front of their name
$name =~ s/Mr//;

print"$namen";
}
close (EMPLOYEES);

Study the script carefully and makesure you understand every part of it. Each instruction was
eitherexplained in this lesson or in one of the previous ones. If you haveany question, do not
hesitate to ask.
In the next lesson we'll look at how tointeract with the filesystem and
the Linux operating system from ourPerl scripts.
LESSION 5

In the previous lesson we learnt about string comparisons and fileparsing. In this lesson we'll see how Perl can interact with
thefilesystem and execute commands in the Linux operating system. We'llthen use what we've learnt to write a little script.
Executing system commands

Perl provides a function called "system" which canexecute a command or a set of commands
directly on the operatingsystem. In fact, Perl passes the command to the operating system,
whichexecutes it, and then returns the result back to Perl.

So, for instance, the following Perl script prints the content of the current directory:

#!/usr/bin/perl

system("ls");

What actually happens is that the Unix process which runs the Perlinterpreter forks and the
newly created child Unix process executes the"ls" command. When the execution finishes, it
returns theexit code of the command back to the Perl interpreter.

If you are familiar with Unix commands exit codes you can test thesuccess of the execution of
your command by assigning the return valueof "system" to a variable, and then evaluate this
variable.For instance:

$lsExecutedSuccessfully = system("ls");

Here, if "ls" executes successfully, the variable$lsExecutedSuccessfully receives the value 0.


This value corresponds tothe successful exit code of the command "ls".

Executing system commands and capturing the output

Sometimes, when you run a Linux command from your Perl script you'remore interested in
what it writes on the screen than in its exit code.For instance, when you execute "ls" you're
more likely tobe interested in the list of files being printed on the screen than inthe value 0
returned by "system".

To achieve this, you can use evaluated quotes "`"instead of "system". Not only does it executes
the command,but it also returns what the commands writes in its standard output:

@files = `ls`;

In this example, the listing of the files returned by"ls" does not appear on the screen. Instead, it
gets storedin the @files array.

Changing the working directory

In the shell you would type "cd /home" to change the workingdirectory to /home. You could
write the following in your Perl script:
system("cd /home");

But it would have no effect. In fact, since the system call forksfrom the process used by the
interpreter, it doesn't change the workingdirectory of your script. Instead, you can use a Perl
function called"chdir":

chdir "/home";

Interacting with the filesystem

Perl provides a lot of functions to interact with the files anddirectories of your filesystem. Here
are some of these handy functions:

chmod

"chmod" changes the permissions of a file or a list of files andreturns the number of files that
were changed. The first argument mustbe the numerical mode. Examples:

chmod 0777, "/home/clem/program.pl";

chmod 0777, @myFiles;

symlink

"symlink" creates a symbolic link. It is the equivalent of "ln -s".The first argument is the file
name, the second argument is the linkname. Example:

symlink "/home/clem/program.pl", "/usr/bin/program";

mkdir

"mkdir" creates a directory. The first argument is the name of thedirectory and the second
argument is the octal mode which defines thepermissions for that directory. For example:

mkdir "/home/clem/perl_programs", 0664;

rename

"rename" is the equivalent of "mv" in Unix. It renames or moves a file. Example:

rename "/home/clem/program.pl", "/home/clem/program";

rmdir

"rmdir" deletes a directory, but only if it is empty. Example:


rmdir "/home/clem/perl_programs";

stat

"stat" returns a 13-element array which represent the properties of a file. The elements of the
array are :

0: $dev, 1: $ino, 2: $mode, 3: $nlink, 4: $uid, 5: $gid, 6: $rdev,7: $size, 8: $atime, 9: $mtime,
10: $ctime, 11: $blksize, 12: $blocks

Example:

stat "/home/clem/program.pl";

unlink

"unlink" deletes a file or a list of files. Example:

unlink "/home/clem/program.pl";

Perl Script Exercise: Netswitch

In this exercise, we want to be able to switch between networks. Wedefined network


configuration files in a directory called "networks".

For instance, here is the content of ./networks/home:

interface=eth2

type=dhcp

proxy=none

And here is the content of ./networks/work:

interface=eth1

type=dhcp

proxy=www-proxy.work.com

proxy_port=8080

The following Perl script takes a network name as its command lineargument, opens the file
with the same name from ./networks and setsthe network interface with the data taken from the
content of that file:

#!/usr/bin/perl

#default values

$interface="none";

$type="none";

$address="none";

$gateway="none";

$dns="none";

$proxy="none";

$proxy_port = "none";

#gather information from the network file

$network = $1;

$networkFile = "./networks/$network";

open (NETWORK, "$networkFile") or die "$networkFile not found or not


readablen";

while ($line = ) {

chomp $line;

($variable, $value) = split /=/, $line;

if ($variable eq "interface") $interface = $value;

elsif ($variable eq "type") $type = $value;

elsif ($variable eq "address") $address = $value;

elsif ($variable eq "gateway") $gateway = $value;

elsif ($variable eq "dns") $dns = $value;

elsif ($variable eq "proxy") $proxy = $value;


elsif ($variable eq "proxy_port") $proxy_port = $value;

#make sure the type and interface are defined

if ($interface eq "none") die "Interface name not definedn";

if ($type eq "none") die "Network type (dhcp, static) not definen";

if ($type eq "dhcp") {

print "Network type: dhcpn";

#just get an IP address and settings from the DHCP Server

system("dhclient");

elsif ($type eq "static") {

print "Network type: staticn";

#bring the interface up

if ($address eq "none") die ("IP address not definedn");

system("ifconfig $interface $address up");

if ($gateway ne "none") {

print "Gateway: $gatewayn";

system("route add default gw $gateway");

if ($dns ne "none") {

print "DNS Server: $dnsn";

$strNameServer = "cat "."'"."nameserver $dns"."' > /etc/resolv.conf";

system($strNameServer);

}
}

else die "Bad network type : $type. Use dhcp or static.n";

Try to understand each line of that script. The script doesn't setthe proxy in APT, Firefox...etc.
See if you can update the script toadd such functionality. Also, it would be great if the script
couldlist the possible networks available when the user types "netswitch-l". As there are many
ways to solve a problem, especially in Perl,please post your solutions and ideas. Together you
should be able towrite a great network switcher.

You now know all you need to start writing this script, however if you have any questions do
not hesitate to ask.
LESSON 6

A good developer is a lazy developer. In IT, laziness is a gift (would you believe). If you've done something before you should not
have to do it again. Or else, maybe it's time to write a script or some lines of code to automate the process so that you won't
ever have to do it again. A good developer spends a lot of time thinking about his tools, and constantly improves his
environment by developing scripts and tools that will help him develop faster.

In the previous lessons we've used a lot of functions that were built-in the language. For
instance, we used "split", "print", "chomp" ...etc. What we haven't done yet, is to define our own
functions. In Perl we call them subroutines.

Subroutines
A subroutine is basically a few lines of code you give a name to. You can then run these lines by
simply calling the subroutine from your script. You can pass arguments from the scripts to the
subroutine, and depending on the subroutine it can return a result or not.

If you've never used any programming language before, you probably don't know what to think
right now. But don't worry, it's very simple. Let's look at an example to make things a little bit
clearer.

Have a look at the following script:

As you probably guessed, this script does something pretty stupid. It shows you the lines which
contain "house" and then the lines which contain "dog" within the file /etc/myProgram/myFile.
It's not what it does that is shocking though, it's how it does it.

Look at the code. It does exactly the same thing twice... once for "house" and once for "dog". If
there was a bug in the way it shows the lines containing "house", would I remember to also fix
the same bug for "dog" when I fix it? Of course not, I'm only human after all.

The idea is simple. Instead of showing the lines which contain "dog" or "house", we'll define a
subroutine which can show lines containing "something". And then we'll call this subroutine
with "dog" and "house".

As you can see, we reduced the amount of code and more importantly, we removed code that
was repeated twice. The first part of the script defines a subroutine called showLines. The
second part simply calls it twice, once giving it the argument "house", and then giving it the
argument "dog".

Within the subroutine, we simply replaced the references to "dog" and "house" with a variable
representing the argument. When you call a subroutine with an argument or a list of arguments,
the subroutine is executed and the arguments are stored in the following array variable: @_.

The line my ($keyword) = @_; is simply assigning the values of the arguments to an array
containing variables. In this case the value of the argument is assigned to $keyword, which
receives "house" and then "dog" when called from the script.

Local variables
The reason why the assignment is preceded by "my" is because we want the $keyword variable
to be local to the subroutine. When a variable is defined with the keyword "my"it becomes a
local variable and it only exists within the subroutine. This way, we do not have to worry
whether or not another variable with the same name is defined in the script. It's always a good
idea to make variables local inside your subroutine, so always declare them with the "my"
keyword.

arguments
Let's go further. Instead of a subroutine which prints the lines containing "something" from the
file /etc/myProgram/myFile, we'll define a subroutine which prints the lines containing
"something" from "some" file. This time we'll use two arguments: the file to look into and the
keyword to search for.

We could even define a subroutine which searches for a keyword in a list of files. For this we
would pass two arguments: a keyword, and an array containing filenames.

In this example, note how the subroutine retrieves the arguments. The array @_ initially
contains two objects, a scalar and an array. By using the "shift" Perl function we retrieved and
deleted the first element of the array and assigned it to the local variable $keyword. We're then
left with @_ only containing the array of filenames.

Returning something
Subroutines can return values. In our previous example, our subroutine was returning nothing.
We were simply calling it and it was outputting some lines on the screen. In this example, we'd
like the subroutine to do the same, but also to count the number of lines it found and to return it.

As you can see, the subroutine simply returns the number of lines by using the "return"
keyword. In the script, the return value is assigned to the variable $nb.

Conclusion
Thanks to subroutines you can now define code which can be called more than once. Through
the use of arguments and return values, you can make your subroutines more flexible. By
extracting common behavior and defining it within subroutines you'll reduce the cost of
maintenance in your scripts and the number of eventual bugs it might contain. In most cases this
will also make your scripts more scalable. In the next lesson we'll look at how to define our
subroutines outside of our script, so that they can be called and used by more than one script.