Perl Cookbook
by Tom Christiansen & Nathan Torkington
Here are the changes made in the 5/99 reprint:
<2> In the 3rd paragraph, changed
0, 0.00, and 0.0000000 are all
to
0., 0.00, and 0.0000000 are all
(3) In the first complete sentence, changed "as with ' here" to read
"as with / here".
(5) The 1st paragraph used to read:
You can use the =~ operator in conjunction with the s///,
m//, or tr//// operators to make them affect only that
portion of the string.
Changed to:
You can use the =~ operator and the s///, m//, or tr////
operators in conjuncton with substr to make them affect only
that portion of the string.
(8) In the 1st paragraph, changed the mention of "Recipe 8.13"
to "Recipes 13.11 or 14.11".
(9) Changed "perlop" to "perldata" under See Also.
(15) Added the missing quotation mark to "Switches" in the
See Also section.
{17} The code comment "single quotes!" now reads "like single quotes!".
(20) The = sign now lines up with the others in the code example at
the top of the page.
(20) Changed "You can also use them to do" to "You can also use
their functional forms to do"
(30) Halfway down, in sub trim: the first 4 lines following
sub trim { were indented one tab-stop too far. The code now reads:
sub trim {
my @out = @_;
for (@out) {
s/^\s+//;
s/\s+$//;
}
(31) Under See Also, changed "trim leading whitespace" to "trim
leading and trailing whitespace", and deleted "and use it when
we separate list elements in Recipe 4.1"
(34) The word "lorrie" was misspelled in the table. Now reads "lorry".
(34) In the paragraph above the code example, changed
A -t to test for an interactive run check tells whether
to
A -t check to test for an interactive run tells whether
{37} The prompt at the bottom-most command is now a "%" like
the rest of them, not a "$".
(45) In the 1st paragraph, changed "Perl's supports the function"
to "Perl supports the function"
{50} In the 1st paragraph, changed "use the $x..$y construct" to
"use the $X .. $Y construct"
(53) Added a semicolon before "Chapter 3" in the See Also section.
(53) Inserted a thinspace after the "y" at the end of "Cryptography"
and its following semicolon.
(64) Changed "to convert from octal and uses hex" to "to convert from
octal and hexadecimal", and changed the font on hexadecimal.
(64) In See Also: removed ";sysopen in covered in Recipe 7.1"
(65) Under Solution, changed "ternary hook" to "ternary conditional".
{65} The middle line of the last code example used to read:
printf "%d hour%s %s enough.\n", $time,
$time==1 ? "" : "s";
$time==1 ? "is" : "are";
It now reads::
printf "%d hour%s %s enough.\n", $time,
$time==1 ? "" : "s",
$time==1 ? "is" : "are";
(67) Changed "huge primes" to "huge integers".
{67} Used to read:
factors 8 9 96 21
Changed to read:
bigfact 8 9 96 2178
{68} Also changed "factors" to "bigfact" for the other two examples.
{68} Changed "bignum" in the program text to "bigfact".
{68} Removed the "$root, " from the declaration
my($n, $root, %factors, $factor);
It now reads:
my($n, %factors, $factor);
(71) The URL in the bottom of the footnote is out of date. Changed to:
http://sciastro.astronomy.net/sci.astro.3.FAQ
(75) Changed $TIME to $time
{77} Changed "Date::DateCalc" to "Date::Calc" throughout page (4 times).
{78} The seconds were wrong in the output. They now read:
There were 265333775 seconds between Nat and Bree
(79) Changed "number of days difference" to "number of days".
(79) The weeks and days were wrong in the output. They now read:
(438 weeks, 4 days, 23:49:35)
(79) Changed both occurrences of "Bree and Nat" to "Nat and Bree".
(79) Changed "easily calculated from the day of the year"
to "easily calculated from the day of the year (but
see discussion below, as standards differ)"
<80> Changed the code in the center of this page as follows:
use Date::Calc qw(Day_of_Week Week_Number Day_of_Week_to_Text)
$year = 1981;
$month = 6; # (June)
$day = 16;
$wday = Day_of_Week($year, $month, $day);
print "$month/$day/$year was a ", Day_of_Week_to_Text($wday), "\n";
## see comment above
$wnum = Week_Number($year, $month, $day);
print "in week number $wnum.\n";
6/16/1981 was a Tuesday
in week number 25.
{84} Changed "seconds between $t1 and $t2" into
"seconds between $t0 and $t1" so it matches the code.
<85> In line 2, reading:
syscall(&SYS_gettimeofday, $start, 0)) != -1
Deleted second right parantheses.
(86) Changed "The Time::HiRes provides to "The Time::HiRes module provides"
(94) The header now reads "Discussion" instead of "Description"
{94} Changed
print "I have @array marbles\n.";
into
print "I have @array marbles.\n";
(95) Changed "conditional operator discussed" to "conditional
operator is discussed"
(97) In the 5th paragraph, changed "entry for $#array" to
"discussion of the $#array notation".
{99} Changed
print "@array";
to
print "@array\n";
{99} Changed
foreach $item (@a, @b) {
$item *= 7;
print "$item ";
}
to
foreach $item (@a, @b) {
$item *= 7;
}
print "@a @b\n";
{102} Changed "@unique" to "@uniq" in the last line on this page.
(107) In the 3rd paragraph of the Discussion, changed "Unlike the
initial solution, the elements..." to "The elements..."
(111) In the 2nd paragraph, deleted the "be" from "isn't be an array"
{114} The code used to read
@MATCHING = ();
foreach (@LIST) {
push (@MATCHING, $_) if TEST ($_)
It now reads:
@matching = ();
foreach (@list) {
push (@matching, $_) if TEST ($_)
{115} The example under Solution used to read:
@Sorted = sort { $a <=> $b } Unsorted;
It now reads:
@sorted = sort { $a <=> $b } @unsorted;
(115) In the 1st paragraph under Discussion, changed "comparison
routine with..." to "comparison subroutine with..."
(120) Changed "remove the temporary array" to
"remove the temporary arrays"
(124) In the 3rd paragraph, 2nd line, changed "longest line seen"
to "length of longest line seen"
(124) In the 3rd paragraph, 3rd line, changed "by the longest input
record seen" to "by the length of the longest input record seen"
{127} Changed "permutation of S objects" to "permutation of $len objects"
(127) Changed Camel:3 to "Chapter 3 of Programming Perl", and
Camel:2 to "Chapter 2 of Programming Perl".
(130) Changed
the discussions of closures in the "Private Variales via my()"
section of perlsub(1) and perlref(1)
to
the discussions of closures in perlsub(1) and perlref(1)
<135> Changed "Use each with while loop:" to "Use each with a while loop:"
{144} Changed
foreach $food (sort { $food_color{$a} cmp $food_color{$b} } )
keys %food_color) {
print "$food is $food_color{$food}.\n";
}
to
foreach $food (sort { $food_color{$a} cmp $food_color{$b} }
keys %food_color)
{
print "$food is $food_color{$food}.\n";
}
(145) In the 1st paragraph under Discussion, changed "we assign it
to %MERGED," to "we assign it to %merged,"
{145} In the last line on the page, changed "%ingested_colors"
to "%ingested_color"
(146) The first $substance_color in this paragraph now lines up
with the second.
(148) Deleted "The explanation of hash slices in perldata(1) and"
under See Also, because this recipe did not discuss them.
(148) In the example under Solution, changed "as the keys to %HASH"
to "as the keys to %hash"
(151) Changed
The first foreach adds one to $count{$element} for each
occurrence of $element.
to
The foreach adds one to $count{$element} for every
occurrence of $element.
(151) In the paragraph under Problem, italicized "of" in the
phrase "the mother of relationship"
{152} Changed
next unless /^\s*#\s+include\s+<([^>]+)>/;
to
next unless /^\s*#\s*include\s*<([^>]+)>/;
{153} Changed "% du cookbook" to "% du pcb"
(154) Changed
contains "yes" and "no", which do not have
to
contains "yes" and "not", which do not have
(155) Changed "contains a reference to an anonymous array containing"
to "contains"
(155) Changed
contains "pcb/rev/yes" and "pcb/rev/no".
to
contains "pcb/rev/yes" and "pcb/rev/not".
{156} Halfway down the page was a line containing nothing but
i}
Deleted the i.
(178) In the 3rd line of code, changed "different liens" to "different lines"
{191} At the bottom of the page, changed "Found numeral..." to
"Found number..." 3 times.
{193} In the 2nd paragraph from the bottom of the page, changed:
and then ""
to:
and then ""
Also changed
corresponding ""
to:
corresponding ""
{200} Changed the comment that used to read:
# look for a lap
It now reads:
# look for a lab
(205) In the 2nd paragraph from the bottom of the page,
changed "an educate guess" to "an educated guess"
{214} The words "usage()" and "new()" used to be italicized;
they are now plain text.
{226} Changed the assignment from $sink to $fh in the program
code example.
{226} On the "$filename for reading" line, changed "for reading"
to "for writing".
(237) In the 2nd paragraph, "See 16.15" now reads "See 16.6"
{251} All three cases in the code that had "vec($r," now have
"vec($rout," instead.
(279) In section 8.2, the first line under "Discussion":
"file size file" now reads "file size".
(285) In the 1st paragraph, changed "file, But you usu-" to
"file, but you usu-"
{287} In the code at the bottom of the page, changed
$tie = tie(@lines, $FILE, O_RDWR, 0666, $DB_RECNO) or die
to
$tie = tie(@lines, "DB_File", $FILE, O_RDWR, 0666, $DB_RECNO) or die
(292) In the 5th paragraph under Discussion, moved the quote and
backslash down to the next line.
{300} The order of tests was reversed. It used to read:
do "$APPDFLT/sysconfig.pl"
or
do "$ENV{HOME}/.myprogrc";
Now reads:
do "$ENV{HOME}/.myprogrc";
or
do "$APPDFLT/sysconfig.pl"
(302) The heading used to read Description. It now reads: Discussion
(303) In the 2nd paragraph, changed
If you don't have an unrestrictedversion
to read:
If you don't have an unrestricted version
(315) In the 2nd paragraph under Discussion, changed "report which
filenames it couldn't delete, only how many." to read "report
which filenames it couldn't delete, only how many it did delete."
(317) Changed "eaily tell" to "easily tell"
{317} In the last line of code, removed the bang, changing:
unless (! $seen{$dev,$ino}++){
to
unless ($seen{$dev,$ino}++){
{324} In the first code example, changed this line:
return if defined $age && $age > -M;
to read:
return if defined $age && $age > (stat($_))[9];
(324) In the paragraph under the first code example, changed
that lets it be called more grep or map.
to read:
that lets it be called like grep or map.
(334} Changed
print "hi there\n!";
To read:
print "hi there!\n";
{336} In the 2nd code example, changed
return sqrt( ($side1 ** 2) + ($side1 ** 2) );
To read:
return sqrt( ($side1 ** 2) + ($side2 ** 2) );
(341) Changed "how many nested subroutine calls" to "how many frames (nested
subroutine calls)"
(358) In the 4th paragraph, changed "too late to useful" to
"too late to be useful"
(366) The 2nd paragraph used to read:
really meant "take the fourth element of @x"
It now reads:
really meant "take the fifth element of @x"
366) Also changed the 5th paragraph to read: "If you call ref on
a non-reference, it returns an empty string."
{371} Changed
# access Nth item (best)
To read:
# access item in position N (best)
(373) Under See Also, changed "Hashs of Arrays" to "Hashes of Arrays".
(373) Changed the text describing the 13.15 recipe to "Tie Example:
Make a Hash That Always Appends".
{373} Code under Solution used to read
"key2" => "value2 ..."
Now reads:
"key2" => "value2", ...
{373} Also in the code, changed
@keys = keys %$hash;
To read:
@keys = keys %$href;
(381) In the 2nd paragraph, changed
the "prev" and "last" values
To read:
the "PREV" and "LAST" values
(385) Under Discussion, deleted: "We'll choose a key called
"Name" to hash them on:"
{385} In the 2nd code example, changed
my @fields = { split /^([^:]+):\s*/m };
to
my @fields = split /^([^:]+):\s*/m;
{385} Also changed
push(@Array_of_Records, { @fields });
to
push(@Array_of_Records, { map /(.*)/, @fields });
{393} In Example 11-1, changed
while ($n++ < 20) { insert($root, int(rand(1000)) }
to
while ($n++ < 20) { insert($root, int(rand(1000))) }
(420) Under See Also, changed the mention of "SelfLoader" in the
SEE ALSO into "AutoLoader".
(429) Changed
MANIFEST | List of files in the distribution
to read as an entry in the table, not a column heading.
(432) Replaced sample paragraph as follows:
If we had a I<.h> file with function prototype declarations,
we could include that, but since we're writing this one from
scratch, we'll use the B<-c> flag to omit building code to
translate any C<#define> symbols. The B<-n> flag says to
create a module directory named I, which will have
the following files.
(446) Changed
$lector = Human::Cannibal->new();
$object->feed("Zak");
$object->move("New York");
to
$lector = Human::Cannibal->new();
$lector->feed("Zak");
$lector->move("New York");
{453} Right above the "bless" line in the example at the bottom,
changed the lone semicolon to read: "};"
{461} Changed the code that read
if (@ISA && $proto->SUPER::can('new') {
to read
if (@ISA && $proto->SUPER::can('new')) {
(469) Last line of code used to read "Jason"; it now reads
"Kid's parent is Jason"
(470) Added a semicolon under See Also. Now reads:
"perltoot(1); Chapter 5 of Programming Perl;"
{477} Changed
sub StrNum($) {
to
sub StrNum {
{484} Changed
push @{$self->{key}}, $value;
To read
push @{$self->{$key}}, $value;
{492} Changed
dbmopen %HASH, FILENAME, 0666 # open database, accessed through %HASH
or die "Can't open FILENAME : $!\n";
To read:
dbmopen %HASH, $FILENAME, 0666 # open database, accessed through %HASH
or die "Can't open $FILENAME : $!\n";
Also added a $ to each occurence of FILENAME, KEY, and VALUE.
(497) Under Discussion, changed "With SDBM or GDBM" to "With SDBM or NDBM"
{512} Added a new final line to this page, indented to the same level
as the chop on the previous line:
next unless defined $href && defined $binary_time;
(518) In the table, changed
option:i | Yes | Optional string parameter:
To read:
option:i | Yes | Optional integer parameter:
(536) Under See Also, changed "by Don Libes, O'Reilly and Associates
(1996?)" to read "by Don Libes, O'Reilly and Associates (1995)"
{539} Changed
my $f = $menubar->Menubutton(-text => "File", -underline => 0,
To read:
my $f = $menubar->Menubutton(-text => "Edit", -underline => 0,
(555) Changed "Chapter 8 of Programming Perl" to "Chapter 6 of
Programming Perl"
{556} Deleted this line: ($pid = fork) ? waitpid($pid,0) : exec(@ARGV)
(last line of code).
(557) Changed Chapter 8 to 6 under See Also.
(565) Changed strange-looking font in the right hand column.
{604} In the 2nd code example, changed
socket(SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
To read:
socket(TO_SERVER, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
{608} Removed the dollar sign in front $SERVER of both calls to fcntl().
(628) Fixed typo in See Also: now reads "The select function in.."
{630} In the code example, changed:
if ($rv == length $outbuffer{$client} ||
{$! == POSIX::EWOULDBLOCK) {
It should read:
if ($rv == length $outbuffer{$client} ||
$! == POSIX::EWOULDBLOCK) {
(632) Fixed typo in See Also: now reads "The select function in.."
{645} Under Discussion, changed "and inet_aton to convert back:" to
read "and inet_ntoa to convert back:"
(651) In the code example under Solution, changed
$mailer = Mail::Mailer->new();
to
$mailer = Mail::Mailer->new("sendmail");
(655) In the last paragraph, changed "NetNews Transfer Protocol" to read
"Network News Transfer Protocol"
{656} In the first code example, changed
or die "Can't fetch article $article_number: $!\n";
To read:
or die "Can't fetch article $message_id: $!\n";
(659) Under See Also, changed "RCS 1734" to "RFC 1734"
(661) Fixed the typo under See Also. It now reads: "The documentation
for the Net::Telnet"
(661) Fixed the typo in the 2nd paragraph under Discussion; 2nd sentence
now reads: "The machine is considered unreachable"
(669) Moved parantheses in the 2nd sentence. Now reads:
(Don't confuse HTTP methods with the methods of
object-orientation. They have nothing to do with
each other).
{677} Changed the version output from "2.40" to "2.49".
(677) Changed last paragraph to read:
prints @INC (Perl's array of directories it looks for
^^^^^
(679) In the third bullet item under Solution, changed "quite by talking"
to "quit by talking".
{691} In example 19-6, changed
my $server = HTTP::Daemon->new(Timeout => 60);
To read:
my $server = HTTP::Daemon->new(Timeout => 60, LocalPort => 8989);
{698} In the 2nd code example, changed
print header("Program Title"), begin_html();
It now reads:
print header("Program Title"), start_html();
(707) In the table, deleted two lines: "LWP::UserAgent" and "URI::URL"
(708) Under Discussion, changed
We use four different modules from LWP.
To read:
We use three modules from LWP and one other from CPAN.
(711) Changed "isn't and " would yield:" to read
"isn't &" would yield:
(716) Under Solution, changed "the LWP modules:" to read "the CPAN modules:"
(717) In the 2nd paragraph, changed "the HTML parsing routines from LWP"
to read "the HTML parsing routines from CPAN"
(717) And in the next paragraph, changed "subclass LWP's HTML::Parser class"
to read "subclass the HTML::Parser class"
{720} In Example 20-6, changed
my($req, $ans);
To read:
my $ans;
{722} In the second code example, changed
{ int($seconds / 60) } minutes.
To read:
{ int($total / 60) } minutes.
(722) Under Discussion, changed "$whats_his_name, $login_count, and
$minute_used" to read "$username, $count, and $total"
{723} In Example 20-7, changed
'total' => $total
To read:
'total' => $seconds
{726} Deleted the pipe and the line between "Disallow: /" and
"User-agent: Mozilla ..."
(737) In the Index, changed
binary numbers, convering with decimal numbers, 48-49
Now reads:
binary numbers, converting with decimal numbers, 48-49
(738) Changed
comments, in regular expressins
To read:
comments, in regular expressions
(741) Changed "escaping chacters" to "escaping characters"
(742) Changed "FileHandler" to "FileHandle"
(746) Deleted "LWP::Heuristic"
(749) Changed "pattern-matching" to "pattern matching"
(749) Changed "multiple-byte charactrs" to "multiple-byte characters"
(750) Added page 110 to prototypes entry
(756) Added page 709 to URI::Heuristic entry