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