|
CSCI A348/A548Lecture Notes 4 Fall 1999 |
A Quick Perl Primer
Let's first write a Perl program and see it run.
Use pico, emacs or another editor and create a file called one with
the following contents:
This is a complete Perl program, but can you run it already?#!/usr/local/bin/perl print "Hello, world!";
Look at the file with the ls command:
(Ask me about mytucotuco.cs.indiana.edu% ls -l one -rw-r--r-- 1 dgerman students 41 Sep 4 15:16 one tucotuco.cs.indiana.edu%
umask value.)
The -rw-r--r-- means that this file can be read and
modified by the owner (dgerman) and can be viewed by the groups to
which the owner belongs to and by the world. To make this file
executable use chmod:
The file is now executable and we can run it:tucotuco.cs.indiana.edu% chmod +x one tucotuco.cs.indiana.edu% ls -l one -rwxr-xr-x 1 dgerman students 41 Sep 4 15:16 one tucotuco.cs.indiana.edu%
Change the program as indicated below:tucotuco.cs.indiana.edu% ./one Hello, world!tucotuco.cs.indiana.edu%
And run it again#!/usr/bin/perl print "Hello, world!\n";
and now we are ready to start our Perl tutorial.tucotuco.cs.indiana.edu% ./one Hello, world! tucotuco.cs.indiana.edu%
The first line in any Perl script must start with a hash sign
(#) followed by an exclamation sign (!)
and then by the absolute address of the perl interpreter
(which perl).
Perl is located in /usr/local/bin/perl on
burrow and on most other Unix systems.
The perl interpreter is, like your web server, just another program.
When a Perl script gets invoked the perl interpreter is located and started (using the first line of the script). The interpreter then takes care of the rest of the file which is, in fact, the Perl program.tucotuco.cs.indiana.edu% ls -l /usr/local/bin/perl -rwxr-xr-x 3 root daemon 794248 Feb 27 1998 /usr/local/bin/perl tucotuco.cs.indiana.edu% tucotuco.cs.indiana.edu% file /usr/local/bin/perl /usr/local/bin/perl: ELF 32-bit MSB executable SPARC Version 1, dynamically linked, not stripped tucotuco.cs.indiana.edu%
We will now provide an introduction to Perl through a set of examples.
1. The empty program is a valid program.
tucotuco.cs.indiana.edu% vi empty tucotuco.cs.indiana.edu% cat empty #!/usr/local/bin/perl tucotuco.cs.indiana.edu% chmod +x empty tucotuco.cs.indiana.edu% ./empty tucotuco.cs.indiana.edu%
2. Scalar variables are identified by a special prefix, the dollar sign. If we wanted to write
a program that computes the value of
3 + 5 and stores that in
a variable with the name of x it could look like this:
Of course this program does not communicate much.tucotuco.cs.indiana.edu% vi two tucotuco.cs.indiana.edu% cat two #!/usr/local/bin/perl $x = 3 + 5; tucotuco.cs.indiana.edu% chmod +x two tucotuco.cs.indiana.edu% ./two tucotuco.cs.indiana.edu%
To print the value of x we use the print command.
tucotuco.cs.indiana.edu% vi two tucotuco.cs.indiana.edu% cat two #!/usr/local/bin/perl $x = 3 + 5; print $x; tucotuco.cs.indiana.edu% ./two 8tucotuco.cs.indiana.edu%
print takes a list of arguments, separated by commas, evaluates
them, and then prints the results to the screen in the order in which they
appear as arguments. $x evaluates to an integer, gets printed,
and then the program terminates. Control returns to the
operating system which prompts the user for more input. Other things that we could print are characters and strings. Let's look at strings first. We could start by saying that strings are sequences of characters that appear in between double quotes. Thus
is a string, and so is"perl"
or"two words"
the last one being a string of exactly 6 blanks." "
So we can change the program that computes
3 + 5 to add a blank space after the result.
This way the result (tucotuco.cs.indiana.edu% vi two tucotuco.cs.indiana.edu% cat two #!/usr/local/bin/perl $x = 3 + 5; print $x, " "; tucotuco.cs.indiana.edu% ./two 8 tucotuco.cs.indiana.edu%
8)
doesn't get as cluttered as before by the prompt.
In strings delimited by double quotes certain combinations of characters have a special,
clearly determined meaning. For example the following group of two characters:
\n
stands for a carriage return (or newline). So if we change the script that computes the results of
3 + 5 and
prints it out to print
"\n"
instead of " " after the result
the output appears on a line of its own:#!/usr/local/bin/perl $x = 3 + 5; print $x, "\n";
tucotuco.cs.indiana.edu% ./two 8 tucotuco.cs.indiana.edu%
3. Lists can be stored in variables that are prefixed by the symbol
@.
Here's a program that assigns a list of integers to a variable
a. Using the foreach construct it
goes over the entire list of variables and adds them up, to print the result at the end.
tucotuco.cs.indiana.edu% vi three
tucotuco.cs.indiana.edu% cat three
#!/usr/local/bin/perl
@a = (1, 2, 3, 4);
foreach $a (@a) {
$sum += $a;
}
print "The sum is: ", $sum, "\n";
tucotuco.cs.indiana.edu% chmod +x three
tucotuco.cs.indiana.edu% ./three
The sum is: 10
tucotuco.cs.indiana.edu%
As they say, by the principle of least surprise the sum
variable gets initialized to 0, and so it's 0
the first time it's used. The foreach loop uses a variable $a
that takes every value in the list @a
in turn; each such value is added to $sum, the statement
$sum += $a;
being a short form of $sum = $sum + $a;
Lists have their elements in a certain order, and indexed by their position in their list.
For example the first element of the list @a has index 0 and can
be referred to as $a[0]. Here's program three modified again to
print the value of the third element of the list, $a[2]. (Note that the first
element having index 0 the third one will have index 2).
A special (and perhaps intimidating) construction gives the index of the last element in listtucotuco.cs.indiana.edu% vi three tucotuco.cs.indiana.edu% cat three #!/usr/local/bin/perl @a = (1, 2, 3, 4); print "The third element has value: ", $a[2], "\n"; tucotuco.cs.indiana.edu% ./three The third element has value: 3 tucotuco.cs.indiana.edu%
@a: $#a
This is very useful if the list changes with time (although we won't have such examples
in this tutorial). Here's a modified version of three that also prints out the
number of elements in the list by using the index of the last element:
If a listtucotuco.cs.indiana.edu% vi three tucotuco.cs.indiana.edu% cat three #!/usr/local/bin/perl @a = (1, 2, 3, 4); print "The third element has value: ", $a[2], "\n"; print "The list has ", $#a + 1, " elements.\n"; tucotuco.cs.indiana.edu% ./three The third element has value: 3 The list has 4 elements. tucotuco.cs.indiana.edu%
@a is empty, then $#a evaluates to -1.
4. A special list @_ is used to hold parameters passed to
functions. Here's the program that uses a subroutine add to add
3 to 5 and then prints the result.
tucotuco.cs.indiana.edu% vi four
tucotuco.cs.indiana.edu% cat four
#!/usr/local/bin/perl
$x = &add(3, 5);
print $x, "\n";
sub add {
local ($a, $b) = @_;
return $a + $b;
}
tucotuco.cs.indiana.edu% chmod +x four
tucotuco.cs.indiana.edu% ./four
8
tucotuco.cs.indiana.edu%
The subroutine is invoked with &.
The definition of the subroutine starts with sub.
The two parameters of the functions are called $a and
$b. They are local to the add
subroutine. The subroutine simply returns the sum of its parameters.
The list of parameters passed to the function can be found in @_
which is a list (@) with a curious name: _ (underscore).
5. A simple example of recursion is the definition of fact a subroutine that
computes the factorial of an integer. For an integer number n the factorial
of n is written n! and is the product of all integers from 1
to n, that is
1 * 2 * ... * (n - 1) * n So, for example,
5! = 1 * 2 * 3 * 4 * 5 = 120
Here's a simple Perl program that computes the factorial of 5.
tucotuco.cs.indiana.edu% vi five
tucotuco.cs.indiana.edu% cat five
#!/usr/local/bin/perl
$n = 5; $x = &fact($n);
print "The factorial of ", $n, " written ",
$n, "! is equal to: ", $x, "\n";
sub fact {
local ($n) = @_;
if ($n == 0) { return 1; }
else { return $n * &fact($n - 1); }
}
tucotuco.cs.indiana.edu% chmod +x five
tucotuco.cs.indiana.edu% ./five
The factorial of 5 written 5! is equal to: 120
tucotuco.cs.indiana.edu%
The == operator is familiar to any C programmer, and so is
the if statement (although in Perl the curly braces are not
optional, they are not optional, they are mandatory).
6. That much about passing parameters to a subroutine. Let's now talk about the way one
passes parameters to the entire program. A special list is holding those values, and its
name is @ARGV. $ARGV[0] is the first command line argument and the index of the last one
is $#ARGV, as expected. Here's a Perl program that prints back its command-line arguments:
tucotuco.cs.indiana.edu% vi six
tucotuco.cs.indiana.edu% cat six
#!/usr/local/bin/perl
foreach $a (@ARGV) {
print $a, "\n";
}
tucotuco.cs.indiana.edu% chmod +x six
tucotuco.cs.indiana.edu% ./six a b c
a
b
c
tucotuco.cs.indiana.edu% ./six
tucotuco.cs.indiana.edu% ./six 1 2 3 4 5 6
1
2
3
4
5
6
tucotuco.cs.indiana.edu%
Try ./six -d . for the fun of it.
7. A simple exercise would be to modify the six program
to distinguish and signal the situation when there are no command-line parameters
passed to the program at all.
tucotuco.cs.indiana.edu% vi six
tucotuco.cs.indiana.edu% cat six
#!/usr/local/bin/perl
if ($#ARGV >= 0) {
foreach $a (@ARGV) {
print $a, "\n";
}
} else {
print "No arguments.\n";
}
tucotuco.cs.indiana.edu% ./six 4 3 2
4
3
2
tucotuco.cs.indiana.edu% ./six
No arguments.
tucotuco.cs.indiana.edu%
8. Let's close our tour of Perl by introducing associative arrays. They are a very natural
way of associating values with a set of distinct keys. For example we have associated host
names and port numbers with usernames. No two usernames in A348/A548 are identical. Each one
identifies a unique person. Each person has been assigned a host name and port number. Here are some fictitious assignments:
Here's a program that creates two associative arrays indexed by usernames, and when invoked with a username on the command line returns the assignments for the owner of that username.LBIRD blesmol 19900 MJORDAN bobac 19901 SPIPPEN degu 19902 TKUKOC jerboa 19903
tucotuco.cs.indiana.edu% vi seven
tucotuco.cs.indiana.edu% cat seven
#!/usr/local/bin/perl
%hostnames = (
LBIRD => blesmol,
MJORDAN => bobac ,
SPIPPEN => degu ,
TKUKOC => jerboa
);
%portnumbers = (
LBIRD => 19900,
MJORDAN => 19901,
SPIPPEN => 19902,
TKUKOC => 19903
);
if ($#ARGV >= 0) {
print $ARGV[0],
"'s web server runs on ",
$hostnames{$ARGV[0]},
" and uses port #",
$portnumbers{$ARGV[0]},
"\n";
} else {
print "No username specified.\n";
}
tucotuco.cs.indiana.edu% chmod +x seven
tucotuco.cs.indiana.edu% ./seven LBIRD
LBIRD's web server runs on blesmol and uses port #19900
tucotuco.cs.indiana.edu%
This concludes our first tour through Perl.