Perl Cookbook by Tom Christiansen & Nathan Torkington This errata page lists errors outstanding in the most recent printing. If you have any error reports or technical questions, you can send them to booktech@oreilly.com. (Please specify the printing date of your copy.) This page was updated on November 13, 2003. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification Confirmed errors: (viii) There's a typo in the table of contents where an additional space appears before 6.4 " Commenting with Regular Expressions". (xxx) first paragraph under "Documentation Conventions": "printer pager" should be "printer paper". (30) The user is correct that the formatting is all askew, and also correct in their suggested fix, to wit: sub trim { my @out = @_; for (@out) { s/^\s+//; s/\s+$//; } return wantarray ? @out : $out[0]; } However, I think they somewhat miss the mark on what to do when a list is passed in while under scalar context. This is an odd situation, such as you see in $string = reverse(@list); So perhaps the same approach should be taken here, amending the return to return wantarray ? @out : "@out"; {31} Change the parse_csv routine to the following: # See MRE2, p214 sub parse_csv { my $text = shift; # record containing comma-separated values my @fields = (); while ($text =~ m{ # Either some non-quote/non-comma text: ( [^"',] + ) # ...or... | # ...a double-quoted field: (with "" allowed inside) " # field's opening quote; don't save this ( now a field is either (?: [^"] # non-quotes or | "" # adjacent quote pairs ) * # any number ) " # field's closing quote; unsaved }gx) { if (defined $1) { $field = $1; } else { ($field = $2) =~ s/""/"/g; } push @fields, $field; } return @fields; } (71) table The variable "$month" is actually "$mon." {163} the last sentence in 4th paragraph before the code, the variables are reversed and must be switched. $' and $` should be $` and $' (Also, make very certain those are symmetric ticks, not a vertical prime.) {166} IN PRINT: "Discussion" section, first paragraph, fourth sentence; The negated character class [^\W\d_] specifies a byte that must not be an alphanumunder, a digit, or an underscore. Should be: The negated character class [^\W\d_] specifies a byte that must be neither a non-alphanumunder, a digit, nor an underscore. [193] Regular expression on last line of page /(BEGIN((?:(?!BEGIN).)*)END)/ Should be: /(BEGIN((?:(?!BEGIN).)*?)END)/ (234) 1st paragraph; Change "The second solution gets a temporary file whose name you can give to another process." to: "The second solution from the Solution section gets a temporary file whose name you can give to another process." (235) 1st paragraph; The sentence: Text after __DATA__ in Primes.pm can be read from the Primes::DATA filehandle. is misleading. The filehandle depends on the package in effect at the __DATA__ token, not on the filename. {266} Example 7.21: at the bottom of the page within the END{} block return rmdir($lockname); Should be: rmdir($lockname); (305) 1st paragraph: now reads "... offers features not found on other version of tee." should read "other versions" instead. [316] Code block; Change the five lines of code that did read: while ($len = sysread IN, $buf, $blksize)) { if (!defined $len) { next if $! =~ /^Interrupted/; die "System read error: $!\n"; } to instead read these seven lines of code: while (1) { $len = sysread IN, $buf, $blksize; if (!defined $len) { next if $! =~ /^Interrupted/; # ^Z and fg, rarely die "System read error: $!\n"; } last unless $len; {330} 1.-7: Unfortunately, you dare not preserve the directory permissions when you first create the directory, because the directory might lack write permission, and all subsequent link operations will then fail. You have to start out with write permission, then go back and tighten up those that lacked it, after all link creation is complete. (Since lacking write permission is rare, a hash of exceptions could be maintained for the cleanup, or you could make a second pass). [325] Change the program listing of Example 9.3 to read as follows. #!/usr/bin/perl # rmtree1 - remove whole directory trees like rm -r use File::Find; die "usage: $0 dir ..\n" unless @ARGV; find { bydepth => 1, no_chdir => 1, wanted => sub { if (!-l && -d _) { rmdir or warn "couldn't rmdir directory $_: $!"; } else { unlink or warn "couldn't unlink file $_: $!"; } } } => @ARGV; [325] first paragraph in the Discussion section should be changed to: File::Find has an alternate interface whose first argument is a reference to a hash of options settings. The C makes C visit all files beneath a directory before the directory itself--exactly what we need to remove a directory and its contents. The C option stops C from descending into directories. Finally, the C option takes a code reference, our old C function. [329] paragraph following "extension" subroutine; Change If you want ".bak" returned, use '\..*?' as the second... to If you want ".bak" returned, use '\.[^.]*' as the second... {457} This bug is a matter of versions. Under Perl release 5.6 and Class::Struct version 0.58, only this line works: @{$p->peers} = ("Wilbur", "Ralph", "Fred"); whereas this one does not, just as the submitted reported: $p->peers( ["Wilbur", "Ralph", "Fred" ] ); # set its peers field However, under Perl release 5.8 and Class::Struct 0.61, I find that {both are, either is} fine. I thus suggest making the two lines in question read: @{$p->peers} = ("Wilbur", "Ralph", "Fred"); # set its peers field $p->peers( ["Wilbur", "Ralph", "Fred" ] ); # also this way in Perl 5.8 [458] sub Person::age, line 5: ; $struct->{'age'} should be $self->{'age'} [510] Under "See Also"; The URL to the DBI docs online is no longer at symbolstone.org. The correct URL to this documentation is now http://dbi.perl.org [634] Add this in the Solution just before the paragraph beginning "Disassociate": Close the three standard filehandles by reopening them to F: for my $handle (*STDIN, *STDOUT, *STDERR) { open($handle, "+<", "/dev/null") || die "can't reopen $handle to /dev/null: $!"; } <752> Index; "Schwartzian Transformation" should be added, indexed to page 120.