A Beginner's Introduction to Perl 5.10
by chromatic, Doug Sheppard
|
Pages: 1, 2
Variables
If functions are Perl's verbs, then variables are its nouns. Perl has three types of variables: scalars, arrays, and hashes. Think of them as things, lists, and dictionaries respectively. In Perl, all variable names consist of a punctuation character, a letter or underscore, and one or more alphanumeric characters or underscores.
Scalars are single things. This might be a number or a string. The name of a scalar begins with a dollar sign, such as $i or $abacus. Assign a value to a scalar by telling Perl what it equals:
my $i = 5;
my $pie_flavor = 'apple';
my $constitution1776 = "We the People, etc.";
You don't need to specify whether a scalar is a number or a string. It doesn't matter, because when Perl needs to treat a scalar as a string, it does; when it needs to treat it as a number, it does. The conversion happens automatically. (This is different from many other languages, where strings and numbers are two separate data types.)
If you use a double-quoted string, Perl will insert the value of any scalar variables you name in the string. This is often useful to fill in strings on the fly:
use feature ':5.10';
my $apple_count = 5;
my $count_report = "There are $apple_count apples.";
say "The report is: $count_report";
The final output from this code is The report is: There are 5 apples..
You can manipulate numbers in Perl with the usual mathematical operations: addition, multiplication, division, and subtraction. (The multiplication and division operators in Perl use the * and / symbols, by the way.)
my $a = 5;
my $b = $a + 10; # $b is now equal to 15.
my $c = $b * 10; # $c is now equal to 150.
$a = $a - 1; # $a is now 4, and algebra teachers are cringing.
That's all well and good, but what's this strange my, and why does it appear with some assignments and not others? The my operator tells Perl that you're declaring a new variable. That is, you promise Perl that you deliberately want to use a scalar, array, or hash of a specific name in your program. This is important for two reasons. First, it helps Perl help you protect against typos; it's embarrassing to discover that you've accidentally mistyped a variable name and spent an hour looking for a bug. Second, it helps you write larger programs, where variables used in one part of the code don't accidentally affect variables used elsewhere.
You can also use special operators like ++, --, +=, -=, /= and *=. These manipulate a scalar's value without needing two elements in an equation. Some people like them, some don't. I like the fact that they can make code clearer.
my $a = 5;
$a++; # $a is now 6; we added 1 to it.
$a += 10; # Now it's 16; we added 10.
$a /= 2; # And divided it by 2, so it's 8.
Strings in Perl don't have quite as much flexibility. About the only basic operator that you can use on strings is concatenation, which is a ten dollar way of saying "put together." The concatenation operator is the period. Concatenation and addition are two different things:
my $a = "8"; # Note the quotes. $a is a string.
my $b = $a + "1"; # "1" is a string too.
my $c = $a . "1"; # But $b and $c have different values!
Remember that Perl converts strings to numbers transparently whenever necessary, so to get the value of $b, the Perl interpreter converted the two strings "8" and "1" to numbers, then added them. The value of $b is the number 9. However, $c used concatenation, so its value is the string "81".
Remember, the plus sign adds numbers and the period puts strings together. If you add things that aren't numbers, Perl will try its best to do what you've told it to do, and will convert those non-numbers to numbers with the best of its ability.
Arrays are lists of scalars. Array names begin with @. You define arrays by listing their contents in parentheses, separated by commas:
my @lotto_numbers = (1, 2, 3, 4, 5, 6); # Hey, it could happen.
my @months = ("July", "August", "September");
You retrieve the contents of an array by an index, sort of like "Hey, give me the first month of the year." Indexes in Perl start from zero. (Why not 1? Because. It's a computer thing.) To retrieve the elements of an array, you replace the @ sign with a $ sign, and follow that with the index position of the element you want. (It begins with a dollar sign because you're getting a scalar value.) You can also modify it in place, just like any other scalar.
use feature ':5.10';
my @months = ("July", "August", "September");
say $months[0]; # This prints "July".
$months[2] = "Smarch"; # We just renamed September!
If an array value doesn't exist, Perl will create it for you when you assign to it.
my @winter_months = ("December", "January");
$winter_months[2] = "February";
Arrays always return their contents in the same order; if you go through @months from beginning to end, no matter how many times you do it, you'll get back July, August, and September in that order. If you want to find the number of elements of an array, assign the array to a scalar.
use feature ':5.10';
my @months = ("July", "August", "September");
my $month_count = @months;
say $month_count; # This prints 3.
my @autumn_months; # no elements
my $autumn_count = @autumn_months;
say $autumn_count; # this prints 0
Some programming languages call hashes "dictionaries". That's what they are: a term and a definition. More precisely, they contain keys and values. Each key in a hash has one and only one corresponding value. The name of a hash begins with a percentage sign, like %parents. You define hashes by comma-separated pairs of key and value, like so:
my %days_in_month = ( "July" => 31, "August" => 31, "September" => 30 );
You can fetch any value from a hash by referring to $hashname{key}, or modify it in place just like any other scalar.
say $days_in_month{September}; # 30, of course.
$days_in_month{February} = 29; # It's a leap year.
To see what keys are in a hash, use the keys function with the name of the hash. This returns a list containing all of the keys in the hash. The list isn't always in the same order, though; while you can count on @months always to return July, August, September in that order, keys %days_in_summer might return them in any order whatsoever.
my @month_list = keys %days_in_summer;
# @month_list is now ('July', 'September', 'August')!
The three types of variables have three separate namespaces. That means that $abacus and @abacus are two different variables, and $abacus[0] (the first element of @abacus) is not the same as $abacus{0} (the value in %abacus that has the key 0).
Comments
Some of the code samples from the previous section contained code comments. These are useful for explaining what a particular piece of code does, and vital for any piece of code you plan to modify, enhance, fix, or just look at again. (That is to say, comments are important.)
Anything in a line of Perl code that follows a # sign is a comment, unless that # sign appears in a string.)
use feature ':5.10';
say "Hello world!"; # That's more like it.
# This entire line is a comment.
Loops
Almost every program ever written uses a loop of some kind. Loops allow you run a particular piece of code over and over again. This is part of a general concept in programming called flow control.
Perl has several different functions that are useful for flow control, the most basic of which is for. When you use the for function, you specify a variable to use as the loop index, and a list of values to loop over. Inside a pair of curly brackets, you put any code you want to run during the loop:
use feature ':5.10';
for my $i (1, 2, 3, 4, 5) {
say $i;
}
This loop prints the numbers 1 through 5, each on a separate line. (It's not
very useful; you're might think "Why not just write say 1, 2, 3, 4,
5;?". This is because say adds only one newline, at the
end of its list of arguments.)
A handy shortcut for defining loop values is the range operator .., which specifies a range of numbers. You can write (1, 2, 3, 4, 5) as (1 .. 5) instead. You can also use arrays and scalars in your loop list. Try this code and see what happens:
use feature ':5.10';
my @one_to_ten = (1 .. 10);
my $top_limit = 25;
for my $i (@one_to_ten, 15, 20 .. $top_limit) {
say $i;
}
Of course, again you could write say @one_to_ten, 15, 20 .. $top_limit;
The items in your loop list don't have to be numbers; you can use strings just as easily. If the hash %month_has contains names of months and the number of days in each month, you can use the keys function to step through them.
use feature ':5.10';
for my $i (keys %month_has) {
say "$i has $month_has{$i} days.";
}
for my $marx ('Groucho', 'Harpo', 'Zeppo', 'Karl') {
say "$marx is my favorite Marx brother.";
}
The Miracle of Compound Interest
You now know enough about Perl -- variables, print/say, and for() -- to write a small, useful program. Everyone loves money, so the first sample program is a compound-interest calculator. It will print a (somewhat) nicely formatted table showing the value of an investment over a number of years. (You can see the program at compound_interest.pl)
The single most complex line in the program is:
my $interest = int( ( $apr / 100 ) * $nest_egg * 100 ) / 100;
$apr / 100 is the interest rate, and ($apr / 100) * $nest_egg is the amount of interest earned in one year. This line uses the int() function, which returns the integer value of a scalar (its value after any stripping off any fractional part). We use int() here because when you multiply, for example, 10925 by 9.25%, the result is 1010.5625, which we must round off to 1010.56. To do this, we multiply by 100, yielding 101056.25, use int() to throw away the leftover fraction, yielding 101056, and then divide by 100 again, so that the final result is 1010.56. Try stepping through this statement yourself to see just how we end up with the correct result, rounded to cents.
Play Around!
At this point you have some basic knowledge of Perl syntax and a few simple toys to play with. Try writing some simple programs with them. Here are two suggestions, one simple and the other a little more complex:
- A word frequency counter. How often does each word show up in an array of words? Print out a report. (Hint: Use a hash to count of the number of appearances of each word.)
- Given a month and the day of the week that's the first of that month, print a calendar for the month.
You must be logged in to the O'Reilly Network to post a talkback.
Showing messages 1 through 27 of 27.
- Thank you!
2009-09-26 09:13:47 Meltin' [Reply]
I was super excited when i found this because the "perldoc perlintro" for me was too hard to follow. You make this sound so easy and doable, so i wrote my first perl script! Not really that long or inventive, but its a great step for being a newb/noob...
Thanks.
---------------------------------------
use feature ":5.10";
# Listing of our headers, representing days of the week.
my @days_of_the_week = ('Sun', "\t", 'Mon', "\t", 'Tue', "\t", 'Wed', "\t", 'Thu', "\t", 'Fri', "\t", 'Sat');
# Says the "@days_of_the_week" with spaces as shown above
say @days_of_the_week;
# Shows what will be going on this week.
my %week_days = ('Sunday' => 'Church', 'Monday' => 'Moan..', 'Tuesday' => 'Work', 'Wed' => 'Report', 'Thu' => 'Work..', 'Friday' => 'Sleep', 'Sat' => 'Write Perl Script!');
# Says the above values underneath the header.
say ($week_days{Sunday}, "\t", $week_days{Monday}, "\t", $week_days{Tuesday}, "\t", $week_days{Wed}, "\t", $week_days{Thu}, "\t", $week_days{Friday}, "\t", $week_days{Sat});
- programming
2009-08-05 12:04:33 Rick Kieckhefer [Reply]
I know this may be a dumb question but I got to ask. Is my experience I've always use midrange system and there is a 'programmers' workbench. The AS/400 had PDM followed by the graphic tool. Before that the Burroughs system I was on also had a programmers workbench. Is there a tool or someplace to enter your Perl scripts? If so, is the tool downloadable.- programming
2009-11-19 05:23:35 USHANABI [Reply]
The folks over at Perl IDE (Integrated Development Environment [which may be analogous to "Workbench" {if you throw in the Perl debugger}]) (http://perlide.org) ran a one week "poll" of the Perl community to see which IDEs people were using and the results were quite amazing. They list the "cross-platform" IDEs right on the home page. But in addtion to the poll results, you'll also want to check out the "Perl Development Tools" chart link from the Perl Monks WWW site!
- programming
- what file type do i enter the code in
2009-06-28 08:07:02 alex10473 [Reply]
I know this must sound stupid but i just obtained a book on spidering hacks from O'Reilly by Heminway and Calishain. I have not done any programming before. After one file was explained which i saved in a .pl extension file, the book then explained a getprint variant. The following code is provided in the book (code is copied out below)
%perl -MLWP::Simple -e "getprint 'http://cpan.org/RECENT'"
Mirrored.BY
MIRRORING.FROM
RECENT
RECENT.html
SITES
SITES.html
AUTHORS/00whois.html
authors/01mailrc.txt.gz
authors/id/A/AB/ABW/CHECKSUMS
authors/id/A/AB/Pod-POM-0.17.tar.gz
The question is where do i enter this code. In the pl file or some other place?- what file type do i enter the code in
2009-08-19 17:36:49 vthakr [Reply]
Actually, you don't enter it into a file at all. The little percent sign at the beginning of the line is the command line prompt, so you enter it there. What's happening here is you are calling the perl program with two options. The first option is -M which allows you to specify a module that you want to load, in this case you are loading the LWP::Simple which, I'm sure, is where you will find the "getprint" function. Second, you are using the -e option which tells the perl program to execute the line passed into it rather than a file, which in this case is the line "getprint 'http://cpan.org/RECENT'".
Hope that helps out.
- what file type do i enter the code in
- calender
2009-05-25 03:12:49 plnjse [Reply]
use feature ':5.10';
use strict;
use warnings;
# Given a month and the day of the week that's the first of that month, print a calendar for the month.
sub main {#main func
my @days = ("mon", "tue", "wed", "thu", "fri", "sat", "sun");
my %months = ("jan" => 31,"feb" => 28,"mar" => 31,"apr" => 30,
"may" => 31,"jun" => 30,"jul" => 31,"aug" => 31,"sep" => 30,
"oct" => 31,"nov" => 30,"dec" => 31);
my $s = 0;#start point
until ($_[0] eq $days[$s]) {#get day num 0 for mon, 1 for tue etc
$s += 1;
}
my $i = 0;#loop var
say "\n@days";
while ($i < $s) {#print spaces where no date exists
print " ";
$i += 1;
}
$i = 1;
while ($i <= $months{$_[1]}) {#print out dates
print $i < 10 ? "$i " : "$i ";# different spacing for 1 and 2 digit dates
$s += 1;
if ($s > 6) {#wrap weeks
$s = 0;
print "\n";
}
$i += 1;
}
}
main(@ARGV);#pass @ARGV as @_
- How to transform?
2009-03-05 01:49:59 Sai Phyo [Reply]
Please tell me,
I want to know how to transform file in Perl
eg.html,xml,excel etc
- Discourage single character variables
2008-12-07 15:26:34 michaelrwolf [Reply]
Good variable names are the best form of documentation. As such, single character variables like $x and $y are best left to graphical programs that deal with cartesian planes.
What's worse, $a and $b are (for hysterical [sic] purposes) global variables! (Of course, you side-stepped this issue with "my $a", but it's a distinction likely lost on beginners.)
I'd suggest that single character variables be avoided, even in trivial code fragments. Modeling best practices starts with snippets.
Perhaps the following variable names are too training-oriented to be of production value, but I've seen training material that replaces the $a/$b/$c example as follows:
my $eight_str = "8"; # Note quotes to create string
# Note: adding a string and concatenating it produce different results...
my $nine_num = $eight_string + "1"; # Coerce string, then perform addition
my $eight_one_str = $eight_str . "1"; # Concatenate two strings
I'm on the fence as to whether the (Hungarian-like) suffixes are helpful. I think they're useful in training code, but don't like to model them to students since they're likely to model this behavior, which as you indicated, is unnecessary in most Perl code since the DWIM-ery will convert it as necessary for the C<+> or C<.> operator's needs.
Nit picking of variable names aside, great article.
2008-10-21 17:58:22 heyhey3 [Reply]
#!/usr/bin/perl
use cgi ':standard':
print "content-type:text/html\n\n";
$x=param('x'):
- Reference word_frequency_counter.pl & calendar.pl
2008-10-12 08:02:11 Devil's Advocate [Reply]
#!/usr/bin/perl
use strict;
use warnings;
use feature ':5.10';
# word_frequency_counter.pl - a word frequency counter
# Author: Mickey Meng
# Print the headers for our report.
say "Word", "\t", "No. of appearence";
# Statistics how often each word shows up in an array of words.
my @sentence = ("I", "love", "my", "country", "and", "my", "family");
my $sentence_length = @sentence;
my %occurence_of_word = ();
for my $i ( 1 .. $sentence_length ) {
$occurence_of_word{$sentence[$i-1]}++;
}
for my $word (keys %occurence_of_word) {
say "$word", "\t", "$occurence_of_word{$word}";
}
#################################################
#!/usr/bin/perl
use strict;
use warnings;
use feature ':5.10';
# calendar.pl - a calendar for the month
# Author: Mickey Meng
# Print the headers for our report.
say "Sun", "\t", "Mon", "\t", "Tue", "\t", "Wed", "\t", "Thu", "\t", "Fri", "\t", "Sat";
# Print the day of the week for each day of the month
my $weekday_firstday = 3;
for my $i (1..($weekday_firstday-1)) {
print "\t";
}
for my $i (1..31) {
if (($i+$weekday_firstday) % 7 == 1) {
print "\n", $i;
}
else {
print "\t" , $i;
}
}
- Frequency counter
2008-08-29 08:25:01 JJJohnSSSmith [Reply]
$words = "some words\non new lines with \t\t tabs and spaces between words";
for $word (split(/\s+/, $words)) { $frequency{$word}++; }
for $word (sort keys %frequency) { print "$word: $frequency{$word}\n"; }
- Frequency counter
2008-07-07 11:22:38 Matt_Jensen [Reply]
i'm reheally trying to understand this.. but i have no idea how to create that word frequency counter.. sure i can make an array with some words i would like to count.. and sure i can make a hash that is supposed to store the number of appearences. but i have absolutly no idea how to make the values in the hash change based on the appearences of individual words in the array. and if i can't Make it count them then it'll just be an array and a hash standing next to each other not working together!?.. i need help!?- Frequency counter
2008-07-07 12:21:48 chromatic1 [Reply]
You can iterate over the array and increment the values of the hash (keyed on the elements of the array), or you can skip the array altogether and increment the values of the hash in place. Does that give you a hint?- Frequency counter
2008-07-07 16:09:24 Matt_Jensen [Reply]
hey. i still don't get it. could you maybe write code to my email? davantyu@hotmail.com
my current code is.
use 5.010;
my %list = (donkey => 0, fish => 0);
my @list = %list;
@list = (donkey, donkey, fish, donkey, donkey, fish);
$list{donkey} + $list[donkey];
say $list{donkey};
which for obvious reasons doesn't work. i've been trying for 5 hours now and my iq lacks the computing power to figure it out.- Frequency counter
2008-07-21 19:29:28 Wang Yang ming [Reply]
it is also wrote like this(very smart):
use 5.010;
my %counts;
my @items = qw(donkey donkey fish donkey donkey fish);
$counts{$_}++ for @items;
say $counts{donkey};
- Frequency counter
2008-07-08 16:08:46 chromatic1 [Reply]
You're pretty close. Here's the way I'd write it:
use 5.010;
my %counts;
my @items = qw(donkey donkey fish donkey donkey fish);
for my $item (@items)
{
$count{$item}++;
}
say $count{donkey};
The secret you missed was iterating over the list of animals and using each value as a key in the hash.
- Frequency counter
- Frequency counter
2008-07-07 13:25:40 Matt_Jensen [Reply]
yeah. thnx =)
- Frequency counter
- Frequency counter
- Bug
2008-05-16 08:12:42 mikefriedman [Reply]
One of your code samples has a major bug. $constitution1776 should really be $constitution1789. :)
- The easiest language to get started with
2008-05-05 19:55:33 zbinxp [Reply]
I was learning regex,which led me here.
As a .net programmer,all the "verbs" and "nouns" really surprise me. Especially the variables can be put into a string, and work well!
The design principle you mentioned:common things should be easy and simple impress me a lot. Great article! Thanks.
- Double New Line?
2008-04-24 14:44:09 christopherbowland [Reply]
Does the line -- say "The report is: $count_report\n"; intend to have the "\n" at the end? My guess is no since that is what the "say" function does, but what would be the result - 2 new lines?
cb- Double New Line?
2008-04-24 16:00:41 chromatic1 [Reply]
The extra \n was a typo, but the results are what you would expect.- Double New Line?
2008-06-06 20:49:25 dantaylor08 [Reply]
lol you can definitely tell he's not used to 'say' yet.
- Double New Line?
- Double New Line?
- What i would like to see
2008-04-24 04:05:17 iyerr [Reply]
First, this was a nice little introduction - covers the basics and not too intimidating to scare away someone new to Perl! I had read on the net that Perl is not clean/readable but atleast looking at this article, i do not think so!
I am at the stage of deciding on which language to choose for a few web projects that i have. I have a dedicated Intel box with Debian OS and Apache 2 web server. So, i guess using Perl should not be a problem.. What i want to know is which is the best way to use Perl - CGI, mod_perl, ? Any preferred templating system or even whether one is necessary. Any best practices for using Perl in web applications? My projects involve the usual form processing and storing/retrieving from databases. Plus there is a community element which means interaction between users needs to be supported..
I have used asp and php before but was looking to consider Perl (given that companies like amazon and ebay are using it, there must be merits.. and who knows Perl6 might be on the horizon soon!). Also, articles like these (http://www.serverwatch.com/tutorials/article.php/3740841) make me have second thoughts about php.
Any advice/articles on these lines would be much appreciated..
Regards
Ram- What i would like to see
2008-06-06 20:50:45 dantaylor08 [Reply]
Perl isn't inherently unreadable. It just requires you to be intelligent enough to know when it's ok to have unreadable (quick and dirty) code, and when you should have pretty code.
- Try looking here
2008-04-24 08:03:45 b2gills [Reply]
http://perl.apache.org/ (http://perl.apache.org/)
- What i would like to see
- Good article
2008-04-23 15:51:25 Michael Cartmell [Reply]
A good introduction, I even learnt (or relearnt, my memory is going;) something about single quoted strings. Just a few small corrections.
my @months = ("July", "August", "September");
my $month_count = @months;
say $month_count; # This prints 2.
That last line should be
say $month_count; # This prints 3.
In "(the value in abacus that has the key 0)." %abacus is missing its %.
This loop prints the numbers 1 through 5, each on a separate line. (It's not very useful; you're likely thinking right now "Why not just write say 1, 2, 3, 4, 5;, and you're right.)
Because the output is different, the single say statement prints "12345".
Also the punctuation is incorrect, there should be a closing quote and probably a question mark.
That is
(It's not very useful; you're likely thinking right now "Why not just write say 1, 2, 3, 4, 5;?", and you're right.)
Although looking at it I'm not sure about the question mark.
Thanks for another great article.
Michael
- Good article
2008-04-23 18:06:10 chromatic1 [Reply]
Thanks for the comments, Michael. I've updated the article appropriately.
- Good article



