Perl Cookbook by Tom Christiansen & Nathan Torkington Here are the changes made in the 9/98 reprint: ix.line5 run-up "Bytes to Read 254". Line 4 now reads 7.15 Determing the Number of Bytes to Read.................254 x "9.11 Sysmlink" changed to "9.11 sysmirror" and "10.14 Redifining There is a spelling error in the 10.14 title! It's redefining, not redifining. xxvi.1.8 discussing how to make ^^^^^^^^^^ should read: "we discuss" instead of "discussing" xxxii: Add "Jason Ornstein" right before "Jason Stewart" in the second set of reviewers. Add "Eric Watt Forste" right after "Eric Eisenhart". 12.3.4 $seen{$1}++; replace $1 with $byte. This is in the first code example on the page. NOT the second. 15.2.2 the Switches'' section add quotes in front of Switches 19.4.-2 $big = "\u$little" should be $big = "\U$little" make sure this is the first display, not the second 19.4.-1 $little = "\l$big" should be $little = "\L$big" also make sure this is the first display, not the second; the second one begins "To alter ..." and is correct as is. 35.-1.-6 while () { 47.-2 The printf has spaces after the % and before the .1f in four places. Those spaces must be removed, leaving "%.1f" instead of "% .1f" as it is now. 52.7 @chars = ( "A" .. "Z", "a" .. "z", 0 .. 9, qw(% ! @ $ % ^ & *)); % appears twice inside the qw( ... ). Delete the first one. 57.-1.1 The sin, cos, and atan2 functions in the "a" in atan2 is not in Courier. Make it so. 67.4.1 The ternary ("hook") operator discussed in ^^^^^^^ wrongly in Courier should be The ternary conditional ("hook-colon") operator discussed in ^^^^^^^ make in Garamonde 68.-1 There for 3 instances of print here, the first two with wrong indents. This: for $factor ( sort { $a <=> $b } keys %factors ) { print "$factor"; if ($factors{$factor} > 1) { print "**$factors{$factor}"; } print " "; Should change to this: (the changed lines are marked with a *; do not include the *, please.) for $factor ( sort { $a <=> $b } keys %factors ) { * print "$factor"; if ($factors{$factor} > 1) { * print "**$factors{$factor}"; } print " "; 72 para. -2, line 3: change "(Before then" to "By 2038" and line 4: remove the close parenthesis. 86.1.3 Change $time = gettimeofday-$t1; to $time = gettimeofday - $begin; 95.-4.-2 the ternary ("hook") operator ^^^^^^^ courier should be the conditional operator ("?:") ^^^^^^^^^^^ Garamond ^^^^^^^ courier 98.-1.1 The should be . 102.3.4 This line unless ($seen{$item}) Should be unless ($seen{$item}) { 127.2.1 The "memorizing" word in the comment should be "memoizing" without the "r". Yes, I'm serious. 133.3.{1,4,5} Change all occurences of $name to $size here 133.5.1 Change $name to $size here also 133. the code line was moved to its own paragraph print "$food is $food_color{$food}.\n 136.4.-2 Change save substantial time and memory to save substantial memory 136.-3.5 Delete Banana is a food. Martini is a drink. 137.-4.1 The "while () {" line is indented 4 extra blanks, and needs to come out flush with the margin. 141.4.-2 The clsoing curly that's directly below the print is in the wrong column. It should be in the same column as the foreach 4 lines above it. 162.3 This should be in a table with the right-hand side in all Garamonde, save for the variables and special characters which should be in Courier. 167.-1.-2 This: not at the edges. For example, "thistle" would be found, but should be not at the edges. And while, "thistle" would be found, The word vis-a-vis has the wrong accent over the a. It's a grave, not an acute accent. Therefore, it should properly be the correct vis-à-vis instead of the incorrect vis-á-vis. ^ ^ should be grave not acute 170.1.-1 The "unlike" here should be separated from the preceding word "generation" by an em dash. 170 and 171 The typesetting of Nth is inconsistent across these two pages. Sometimes the N is italic; at other times, it is not. I tend to think it shouldn't be italic at all on 170, making it the way they are on 171. But an alternative change is to italicize all the Nth occurrences on 171. I think if you do, that the th superscript should also be in italics. Hm, the title of 6.5 has a non-superscripted th -- that should be fixed. 177.-2.3 The comment on the second while is copied from the first one, but no longer applies. # line is between BEGIN and END # inclusive. Should be # operate only between first and last line, inclusive. 178.2.3 The comment on the second while is copied from the first one, but no longer applies. # line is between BEGIN and END, but not same line Should be # operate only between first and last line, but not same (Yes, this is essentially the same issue on two successive pages) 179.1.2 The comment # previous command fails should be # previous command FAILS 179.6.3 The eof() in the code should not be slant courier, but rather just regular courier like the part all around it. 184.1.1 The /0 modifier should be /o -- that's a letter, not a digit. 186.-3.2 "", "*** GET RICH ***", or "+5-i". These double quotes are all vertical Roman double quotes, not vertical Courier double quotes. 193.-2.3 The second "" on this line should be "" instead. 193.-2.-2 The second "" on this line should be "" instead. 193.4.1 Change "from HTML correctly" to "from all possible HTML correctly". 201.-2.-1 You keep removing my joke: having pity on those who come after you. which really is supposed to read: having pity on those who come after you--before they do. And I wish it were put back. :-( 211.3 My original wording with "can" got altered to this: enhancements are that it ignores anything that's not a plain text file, automatically expands compressed or gzipped files, recurses down directories, searches complete paragraphs or user-defined records, looks in younger files before older ones, and adds underlining or Which to my ear implies it should always to that. But it doesn't. enhancements are that it can ignore anything that's not ^^^^^^^^^^ a plain text file, automatically expand compressed or ^^^^^^ gzipped files, recurse down directories, search ^^^^^^ ^^^^^^ complete paragraphs or user-defined records, look in ^^^^ younger files before older ones, and add underlining or 219 The snippet on ``Remove directory components from program name and arguments'' has been hopelessly mangled. It should read: ($name = " $0 @ARGV") =~ s, /\S+/, ,g; 219 This is wrong: $initial = m/^\S+\s+(\S)+\s+\S+/ ? $1 : ""; It should be ($initial) = m/^\S+\s+(\S)+\s+\S+/ ? $1 : ""; ^ ^ 237.2.1 Change "less than symbol" to "less-than symbol". 237.2.-1 Change ""> $ARGV" to "< $ARGV". 237.2.-1 Change "this use of open" to "this use of magic open". 243.2.-1 Delete the line: % perl -i.old -ne 'print unless /^START$/ .. /^END$/' bigfile.text 250 frombooktech 263.1.2 Change "data structures" to "data structure". 263.-2.-4 Change Perl wouldn't give a ``print on closed filehandle warning even though to Perl wouldn't give a "print on closed filehandle" warning even though ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note change of quotes to vertical primes, and put that quoted string all in Courier, as on the previous page. 264.1.-2 Change "on the rare system" to "on the increasingly rare system". 264.2.-2 Change you lock filenames, To you lock file names, ^^^^^ place the word "names" in italics. 264.3.1 Change "use it lock" into "use it to lock". 264.-4.-1 change "if various" into "should various". 276.-4.-2 Change: Perl also provides unbuffered I/O operations: sysopen, sysread, syswrite, sysseek, and close. Buffering, sysopen, and close are discussed in Chapter 7. into Perl also provides unbuffered I/O operations: sysread, syswrite, and sysseek, all discussed in Chapter 7. 279.3.1 Change "/n" into "\n". Oh my. 283.5.3 You can also use POSIX::clearerr No you can't. POSIX::clearerr says "use IO::Handle::clearerr instead". Remove this sentence, and 284.6 also remove the See Also bit on page 284 that points people to the POSIX module. 285.5 The italic instances of N here should not be slanted. 285.6.2 change "proportionate" to "proportional" 285.6.2 "to size of the file" should be "to the size of the file" or "to the file's size". 293.1.2 Change "read 90 just bytes" into "read just 90 bytes". 293.-4.-2 The em dash follwoing GUI should actually be a close parenthesis, which is otherwise missing. 311.-2.-1 The -C operator was forgotten! Add below -A: -C ctime Same for inode change time (not creation) 312.1.1 The word "stat' there should be in Courier, not Italics. 313.2.2 If you possibly can, change list the same inode number, Into list the same inode number (like vi and nvi in the earlier table) And make sure vi and nvi are in italic. 316.-3 The line with next if $! =~ /^Interrupted/; could stand a comment: next if $! =~ /^Interrupted/; # ^Z and fg 316.-3 The "\en" in the code example must be "\n" instead. 329.-4.2 The sentence-ending period after ".bak" is in the wrong font. It should be Garamonde, not Courier. 329.-3.2 The comma is wrong here!!!! to be "lib/," whereas It needs to be to be "lib/", whereas And for that matter, the second vertical primes are in the wrong font. They are in non-courier, but should be courier. 329.-1 The name of the program in the A-header must be "symirror" not "symlink". Notice the name on the next page. 350.2.1 Delete the word "again" from "repeat again". 350.middle All three instances of "3 , 5" have an extra space before comma that should not be there. 350.-4.2 The function "time" is in garamonde, but needs to be in courier. 351.1.3 This sentence is twisted: The requirement of the backslash that the argument begin with the backslashed type character is sometimes restrictive. Make it read: A backslash in a prototype requires that the argument actually begin with the literal type character, which can sometimes be annoying. 351.2.1 Move the # WRONG over left and align with the # RIGHT below 351.4.1 Unlike the one above it, the second mypush line needs both its arrays backslashed. Make it read: mypush( @{ $x > 10 ? \@a : \@b }, 3, 5); # RIGHT ^ ^ ^ add these tab this 356.-2.-2 Move the grow() over to the right to line up with the word local right above it! 356 There is a spelling error in the 10.14 title. It's "redefining", not "redifining". 365.5.1 Change "it may look as though a reference were litte more" into "a reference might look like little more", since the same construct is already too prevalent. 366.-4.1 Change $rv = \@array; into $aref = \@array; 367.-4.-1 Change It's best to use IO::Handle->new() for them into It's best to use Symbol::gensym() or IO::Handle->new() to ^^^^^^^^^^^^^^^^^^^ generate them 375.3.-2 Change Symbolic references are usually a bad idea. into Symbolic references to variables are usually a bad idea. ^^^^^^^^^^^ 379.4.-1 Currently it says: ($a, $b, $c, $d) = (1 .. 4); # initialize @array = (\$a, \$b, \$c, \$d); # refs to each scalar @array = \( $a, $b, $c, $d); # same thing! Add a line making it: ($a, $b, $c, $d) = (1 .. 4); # initialize @array = (\$a, \$b, \$c, \$d); # refs to each scalar @array = \( $a, $b, $c, $d); # same thing! @array = map { \my $anon } 0 .. 3; # allocate 4 anon scalarresf 392.-1.-2 change "insert an empty node" to "insert into an empty node". 406.4.-2 The non-word "barework" with a `k' should really be "bareword" with a `d'. 406.5.1 Change A better implementation would look like: into A better implementation might look more like: 414.2.-3 "When you--or more likely your system administrator--install this module, its components go" changed to "When you or (more likely) your system administrator installs this module, its components go" 414.4.1 changed So sometimes none of the @INC directories works out to So sometimes none of the @INC directories work out 414.-3.2 Change "directories to @INC" into "directories", since otherwise it won't parse. 417.-1.-2 There's a duplicate word at "also also". Remove either of them, but not both. :-) 433.3.-1 ``for later,'' or ``for nobody'': delete the comma. 453.-2.2 Change use vars qw($NAME $AGE $PEERS); to use vars qw($NAME $AGE @PEERS); 454.2.1 Change "same name" to "same names" to accord with "globals" earlier in the sentence. 504.-2.1 Change "DataDumper" to "Data::Dumper". 505.1.-1 The output line is wrong. It should be: Tom Toming: ARRAY(0x73048) ARRAY(0x73e4c) 508.3 $sth = DBI->prepare(SQL) should read $sth = $dbh->prepare($sql) 523.3.1 This: print colored("venom lack\n", "red on_black"); should be print colored("venom lack\n", "red", "on_black"); 529.1.1 Put a space between "-1parameter" to make it "-1 parameter". 529.-2.-2 The arguments here should be in parens. Make this: ReadMode 'noecho'; $password = ReadLine 0; Be this: ReadMode('noecho'); $password = ReadLine(0); 531.2.-1 The last line of the code reads $term->addhistory($seed_line); But it should read $term->addhistory($cmd); 555.1.1 Prefix this page with: A high-level workaround is given in Recipe 19.6. 555.3.-1 Add a See Also reference to Recipe 16.10 561.1.-1 You can interpret its contents as described in Recipe 16.2. replace "16.2" with "16.19" 567.4.1 # system("prog args 2>&1 1>tmpfile"); this line should be aligned with the next, as it is in the first code chunk on the page 576.-4.-1 Add a See Also to Recipe 19.6 577.4.1 open(FIFO, "> /path/to/named.pipe") or die $1; replace "$1" with "$!" 583.1.1 you also have to use @signame and %signo delete "also", "@", and "%" 584.3.1 Change "systems ties" to "system ties". 588.1.-4 Release 5.005 of Perl will support lightweight delete "will", replace "support" with "supports" 588.1.-3 but it had not been released when this book went to print delete from "but it had" to "to print". And change "5.005 will support" to "5.005 supports". 588.-4 # ... $SIG{INT} = \&catcher; swap the order of these two lines, so that $SIG{INT} appears before the #... 591.4.5 This code while ($stiff = waitpid(-1, &WNOHANG) > 0) { must be while (($stiff = waitpid(-1, &WNOHANG)) > 0) { 592,-2 use POSIX qw(:signal_h :errno_h); replace with use POSIX qw(:signal_h :errno_h :sys_wait_h); 595.1 If an unexpected exception occurs, the alarm never got cleared! Duplicate the alarm(0) line. Make this: } else { die; # propagate unexpected exception } Read this: } else { alarm(0); # clear the still-pending alarm die; # propagate unexpected exception } 602.3.-1 Add at the end of the paragraph, following "send and recv.", this: (Perl does not currently support sendmsg(2).) And make sendmsg be italic. 610.3 setsockopt(SOCKET setsockopt(SOCKET in both cases, change SOCKET to SERVER 610.-1.3 # repeat calls to vec() for each socket to check put "vec()" in Courier not Italic Courier 610.-1.-3 if (vec($rout, fileno(socket), 1)) { change "socket" to "SOCKET" 612.3 socket(Sockhandle, PF_INET, ... change "SockHandle" to "SOCKET" 612.7 send(SockHandle, $MSG, 0, $portaddr) == length($MSG) change "SockHandle" to "SOCKET" 612.9 $portaddr = recv(Sockhandle, $MSG, $MAXLEN, 0) ... change "SockHandle" to "SOCKET" 620.5.2 ($kernel, $hostname, $release, $version, $hardware) = uname(); put "uname()" in Courier not Italic Courier 624.-1.2 use POSIX qw(: sys_wait_h); delete the space after the colon 636.-3.1 "configurations file" should be "configuration file". 638.-1.-2 The errant "Example 17-8" in the middle of the code must be deleted. 642.-1.1 Somehow these are in the wrong format. This should reference Recipe 16.19 and Recipe 17.10, not by name. 645.1.-1 # @addresses is a list of IP addresses ("208.201.239.48", "208.2 01.239.48") change the last "48" to "49" 646.-1 #/usr should be #!/usr or die "Can't find MX records for $host (".$res->errorstring,")\n"; replace "," with "." 681.3.1 Change Race even conditions crop up in apparently to Race conditions crop up even in apparently 688 code while (@row = $sth->fetchrow()) { replace "fetchrow" with "fetchrow_array" 692.-1.1 Recipe 14.10 replace "14" with "19" 692.3.1 Put the word GET in italic. 708.-4.-1 lines of content delete "lines" replace with "bytes" 709 code align the comments beginning with # and or die "usage: $0 url\n"; the final } in the program should be at the start of a new line 709.1 LWP::Heuristic Should read: URI::Heuristic 711.2.2 script.cgi?field=... indent the line some more to make it obvious that it is a continuation. 711.-1.1 Use the HTML::LinkExtor module from LWP delete "LWP" replace with "CPAN" 719.2 Here's an example of a program run: This should be Garamond, not courier. 721.-2 open(F, "< $filename") Replace with open(F, "< $filename\0") 722.1.1 simple.template for internal template() function "template()" should be in Courier not Italic Courier 723.1 "dbi:mysql:connections:mysql.domain.com:3306" delete ":3306" 723.1 if (@row = $sth->fetchrow()) { replace "fetchrow" with "fetchrow_array" 723.1 print header(); put parentheses in Courier not Italic Courier 723.4 but they can also include full code expressions delete "code" 723.-1 "dbi:mysql:connections:mysql.domain.com:3306" delete ":3306" 724.1 if (@row = $sth->fetchrow()) { replace "fetchrow" with "fetchrow_array" 727.1.4 /^(\S+) (\S+) (\S+) \[([^:]+):(\d+:\d+:\d+) ([^\]]+) " Should be: /^(\S+) (\S+) (\S+) \[([^:]+):(\d+:\d+:\d+) ([^\]]+)\] " (that is, add the \] before the space and doublequote. 727.1 (\S+) (\S+)$/; replace ";" with " or next"; 727.4.2 If IDENT (RFC 1413) was used, what it returned add ", otherwise C<->" (courier dash) 727.5.2 , whom they logged in as add ", otherwise C<->" (courier dash) 727.6.2 Date of request (01/Mar/1997) insert "e.g.," after open parenthesis. 727.7.2 Time of request (12:55:36) insert "e.g.," after open parenthesis. 727.8.2 Iime zone (-0700) replace "Iime" with "Time" insert "e.g.," after open parenthesis. 727.9.2 Method of request (GET POST PUT) insert "e.g.," after open parenthesis. replace "GET POST PUT" with "GET, POST, or PUT" 727.10.2 URL in request (/~user/index.html) insert "e.g.," after open parenthesis. 729.-3 Used to read: format STDOUT = @>>>>>>>>>> @>>>>>> @>>>>>>> @>>>>>>> @>>>>>> @>>>>>> @>>>>>>>>>>>>> $lastdate, scalar(keys %hosts), $count, scalar(keys %what), $posts, $home, $bytesum . Now reads: format STDOUT = @>>>>>>>>>> @>>>>>> @>>>>>>> @>>>>>>> @>>>>>> @>>>>>> @>>>>>>>>>>>>> { $lastdate, scalar(keys %hosts), $count, scalar(keys %what), $posts, $home, $bytesum } . 731.5.2 ment text to read ``photo'.' It prints the new document replace "'.'" with "''." 733.3.1 This version of hrefsub will always lowercase the put in Courier 733 add to the end of the page: Example 20-12. hrefsub #!/usr/bin/perl -w # hrefsub - make substitutions in fields of HTML files # from Gisle Aas sub usage { die "Usage: $0 ...\n" } my $from = shift or usage; my $to = shift or usage; usage unless @ARGV; # The HTML::Filter subclass to do the substitution. package MyFilter; require HTML::Filter; @ISA=qw(HTML::Filter); use HTML::Entities qw(encode_entities); sub start { my($self, $tag, $attr, $attrseq, $orig) = @_; if ($tag eq 'a' && exists $attr->{href}) { if ($attr->{href} =~ s/\Q$from/$to/g) { # must reconstruct the start tag based on $tag and $attr. # wish we instead were told the extent of the 'href' value # in $orig. my $tmp = "<$tag"; for (@$attrseq) { my $encoded = encode_entities($attr->{$_}); $tmp .= qq( $_="$encoded "); } $tmp .= ">"; $self->output($tmp); return; } } $self->output($orig); } # Now use the class. package main; foreach (@ARGV) { MyFilter->new->parse_file($_); } 735: Add a new sub-entry under $_ of: [ $_ variable, ] accidental clobbering, 99 735: Change the name of the <> operator from "circumfix" to "diamond". Circumfix is its class, not its name. 735: Insert in the numbers section : "1 while", 16 735: Insert in the numbers section : "0 but true", 348, 608 736: Insert: Alias module, 453 736: Insert as a sub-entry under aliases: [ aliases, ] for functions, 357 736: Insert: autovivification, 367-368 737: Move the entry on circumfix operator and make it be diamond operator instead. 738: Add to the entry on closures: 37, 357, 360, 424 739: Add to the entry on daemon servers: 596 739: Add to the entry on DBI module: 688, 723 740: Add a new entry for "directory handles, 319" either as its own entry or as a sub-entry to the "directory" entry. 740: changed the entry reading /e pattern matching modifier, 169 to /e substitution modifier, 18, 163, 169 740: Add to the /ee entry: /ee substitution modifier, 169 741: Add a new entry (perhaps doing something with the now two evals) eval, in substitution, 18, 163, 169 742: Add a new sub-entry under filehandles: [ filehandles, ] local, 257, 354, 742: Add a new sub-entry under filehandles: [ filehandles, ] passing, 255, 257, 354, 411 742: And a new entry for fmt program, 28 743: Add to the sub-entry on hashes, adding elements to: 351 744: Add to the entry on importing from modules: 357 744: Add to the entry on indirect filehandles: 256-258 745: Add to the entry on ioctl: 427 745: Add a new entry on LINE: (implicit loop label) 239 747: Add to the entry on non-blocking I/O: 608 747: Change the /o pattern-matching operator to /o pattern-matching modifier 749: Add a new sub-entry on pattern-matching [pattern matching, ] progressive (with /g), 170 749: Add a new sub-entry on POSIX [POSIX, ] setsid function, 635 750: Add a new sub-entry under processes [processes, ] groups, 268, 584 751: Change [references, ] as hash elements, 148-149 to [references, ] as hash values, 148-149 751: Add a new subentry under references: [references, ] as hash keys, 486 751: Add a new sub-entry under references: symbolic references, 17-18, 423-424 752: Add to the sub-entry on select, reading from multiple filehandles: 610-611 752: Add a new entry: shopping cart, 696 752: Add a new subentry under signals: process groups, 268, 584 753: Insert under sockets: sockets, non-blocking 608 754: Add a new entry on Sys:Syslog module, 637 755: Add a new entry: typeglobs, 40, 256-258, 262, 355-358 755: Add to the entry on unbuffered input/output: 524-531 757: Add to the entry on window size, determining: 427 757: Add a new entry: Year-2000 problem, 72