=head1 NAME
-perlfaq - frequently asked questions about Perl ($Date: 2002/03/11 21:32:23 $)
+perlfaq - frequently asked questions about Perl ($Date: 2002/11/13 06:23:50 $)
=head1 DESCRIPTION
=item *
+How do I find which modules are installed on my system?
+
+=item *
+
How do I debug my Perl programs?
=item *
=item *
-Is it unsafe to return a pointer to local data?
+Is it safe to return a reference to local or lexical data?
=item *
=item *
-How can I access/change the first N letters of a string?
+How can I access or change N characters of a string?
=item *
=item *
-How can I split a [character] delimited string except when inside
-[character]? (Comma-separated files)
+How can I split a [character] delimited string except when inside [character]?
=item *
=item *
+How can I use Perl's C<-i> option from within a program?
+
+=item *
+
How do I make a temporary file name?
=item *
=item *
-How can I catch accesses to undefined variables/functions/methods?
+How can I catch accesses to undefined variables, functions, or methods?
=item *
for any particular purpose whatsoever. The authors accept no liability
in respect of this information or its use.
-=head1 Changes
-
-=over 4
-
-=item 1/November/2000
-
-A few grammatical fixes and updates implemented by John Borwick.
-
-=item 23/May/99
-
-Extensive updates from the net in preparation for 5.6 release.
-
-=item 13/April/99
-
-More minor touch-ups. Added new question at the end
-of perlfaq7 on variable names within variables.
-
-=item 7/January/99
-
-Small touch ups here and there. Added all questions in this
-document as a sort of table of contents.
-
-=item 22/June/98
-
-Significant changes throughout in preparation for the 5.005
-release.
-
-=item 24/April/97
-
-Style and whitespace changes from Chip, new question on reading one
-character at a time from a terminal using POSIX from Tom.
-
-=item 23/April/97
-
-Added http://www.oasis.leo.org/perl/ to L<perlfaq2>. Style fix to
-L<perlfaq3>. Added floating point precision, fixed complex number
-arithmetic, cross-references, caveat for Text::Wrap, alternative
-answer for initial capitalizing, fixed incorrect regexp, added example
-of Tie::IxHash to L<perlfaq4>. Added example of passing and storing
-filehandles, added commify to L<perlfaq5>. Restored variable suicide,
-and added mass commenting to L<perlfaq7>. Added Net::Telnet, fixed
-backticks, added reader/writer pair to telnet question, added FindBin,
-grouped module questions together in L<perlfaq8>. Expanded caveats
-for the simple URL extractor, gave LWP example, added CGI security
-question, expanded on the mail address answer in L<perlfaq9>.
-
-=item 25/March/97
-
-Added more info to the binary distribution section of L<perlfaq2>.
-Added Net::Telnet to L<perlfaq6>. Fixed typos in L<perlfaq8>. Added
-mail sending example to L<perlfaq9>. Added Merlyn's columns to
-L<perlfaq2>.
-
-=item 18/March/97
-
-Added the DATE to the NAME section, indicating which sections have
-changed.
-
-Mentioned SIGPIPE and L<perlipc> in the forking open answer in
-L<perlfaq8>.
-
-Fixed description of a regular expression in L<perlfaq4>.
-
-=item 17/March/97 Version
-
-Various typos fixed throughout.
-
-Added new question on Perl BNF on L<perlfaq7>.
-
-=item Initial Release: 11/March/97
-
-This is the initial release of version 3 of the FAQ; consequently there
-have been no changes since its initial release.
-
=back
=head1 NAME
-perlfaq1 - General Questions About Perl ($Revision: 1.8 $, $Date: 2002/04/07 18:46:13 $)
+perlfaq1 - General Questions About Perl ($Revision: 1.10 $, $Date: 2002/08/29 03:34:00 $)
=head1 DESCRIPTION
and http://archive.develooper.com/perl5-porters@perl.org/
or the news gateway nntp://nntp.perl.org/perl.perl5.porters or
its web interface at http://nntp.perl.org/group/perl.perl5.porters ,
-or read the faq at http://perlhacker.org/p5p-faq ,
+or read the faq at http://simon-cozens.org/writings/p5p-faq ,
or you can subscribe to the mailing list by sending
perl5-porters-request@perl.org a subscription request
(an empty message with no subject is fine).
=head1 NAME
-perlfaq2 - Obtaining and Learning about Perl ($Revision: 1.13 $, $Date: 2002/04/26 16:56:35 $)
+perlfaq2 - Obtaining and Learning about Perl ($Revision: 1.17 $, $Date: 2002/11/16 23:33:08 $)
=head1 DESCRIPTION
=head2 What modules and extensions are available for Perl? What is CPAN? What does CPAN/src/... mean?
-CPAN stands for Comprehensive Perl Archive Network, a ~700mb archive
+CPAN stands for Comprehensive Perl Archive Network, a ~1.2Gb archive
replicated on nearly 200 machines all over the world. CPAN contains
source code, non-native ports, documentation, scripts, and many
third-party modules and extensions, designed for everything from
http://perldoc.cpan.org/
http://www.perldoc.com/
- http://reference.perl.com/query.cgi?tutorials
http://bookmarks.cpan.org/search.cgi?cat=Training%2FTutorials
=head2 What are the Perl newsgroups on Usenet? Where do I post questions?
ISBN 1-930110-00-6 [1st edition 2001]
http://www.manning.com/cross
- Mastering Perl/Tk
+ Mastering Perl/Tk
by Steve Lidie and Nancy Walsh
ISBN 1-56592-716-8 [1st edition January 2002]
http://www.oreilly.com/catalog/mastperltk/
=head2 Perl on the Net: FTP and WWW Access
-To get the best performance, pick a site from
-the list below and use it to grab the complete list of mirror sites
-which is at /CPAN/MIRRORED.BY or at http://mirror.cpan.org/ .
-From there you can find the quickest site for you. Remember, the
-following list is I<not> the complete list of CPAN mirrors
-(the complete list contains 165 sites as of January 2001):
-
- http://www.cpan.org/
- http://www.perl.com/CPAN/
- http://download.sourceforge.net/mirrors/CPAN/
- ftp://ftp.digital.com/pub/plan/perl/CPAN/
- ftp://ftp.flirble.org/pub/languages/perl/CPAN/
- ftp://ftp.uvsq.fr/pub/perl/CPAN/
- ftp://ftp.funet.fi/pub/languages/perl/CPAN/
- ftp://ftp.dti.ad.jp/pub/lang/CPAN/
- ftp://cpan.if.usp.br/pub/mirror/CPAN/
-
-One may also use xx.cpan.org where "xx" is the 2-letter country code
-for your domain; e.g. Australia would use au.cpan.org.
-[Note: This only applies to countries that host at least one mirror.]
+To get the best performance, pick a site from the list at
+http://www.cpan.org/SITES.html . From there you can find the quickest
+site for you.
+
+You may also use xx.cpan.org where "xx" is the 2-letter country code
+for your domain; e.g. Australia would use au.cpan.org. [Note: This
+only applies to countries that host at least one mirror.]
=head2 What mailing lists are there for Perl?
A comprehensive list of Perl related mailing lists can be found at:
- http://lists.cpan.org/
-
-( also visible as http://lists.perl.org/ )
+ http://lists.perl.org/
=head2 Archives of comp.lang.perl.misc
=head1 NAME
-perlfaq3 - Programming Tools ($Revision: 1.22 $, $Date: 2002/05/06 13:11:13 $)
+perlfaq3 - Programming Tools ($Revision: 1.29 $, $Date: 2002/11/13 06:23:50 $)
=head1 DESCRIPTION
from the source distribution is simplistic and uninteresting, but
may still be what you want.
+=head2 How do I find which modules are installed on my system?
+
+You can use the ExtUtils::Installed module to show all
+installed distributions, although it can take awhile to do
+its magic. The standard library which comes with Perl just
+shows up as "Perl" (although you can get those with
+Mod::CoreList).
+
+ use ExtUtils::Installed;
+
+ my $inst = ExtUtils::Installed->new();
+ my @modules = $inst->modules();
+
+If you want a list of all of the Perl module filenames, you
+can use File::Find::Rule.
+
+ use File::Find::Rule;
+
+ my @files = File::Find::Rule->file()->name( '*.pm' )->in( @INC );
+
+If you do not have that module, you can do the same thing
+with File::Find which is part of the standard library.
+
+ use File::Find;
+ my @files;
+
+ find sub { push @files, $File::Find::name if -f _ && /\.pm$/ },
+ @INC;
+
+ print join "\n", @files;
+
+If you simply need to quickly check to see if a module is
+available, you can check for its documentation. If you can
+read the documentation the module is most likely installed.
+If you cannot read the documentation, the module might not
+have any (in rare cases).
+
+ prompt% perldoc Module::Name
+
+You can also try to include the module in a one-liner to see if
+perl finds it.
+
+ perl -MModule::Name -e1
+
=head2 How do I debug my Perl programs?
Have you tried C<use warnings> or used C<-w>? They enable warnings
as it were. A more complete example, with comments, can be found at
http://www.cpan.org/authors/id/TOMC/scripts/toms.exrc.gz
-The a2ps http://www-inf.enst.fr/%7Edemaille/a2ps/black+white.ps does
+The a2ps http://www-inf.enst.fr/%7Edemaille/a2ps/black+white.ps.gz does
lots of things related to generating nicely printed output of
documents, as does enscript at http://people.ssh.fi/mtr/genscript/ .
=back
-For Windows there's also the
-
-=over 4
-
-=item CodeMagicCD
-
-( http://www.codemagiccd.com/ ) Collection of various programming
-tools for Windows: Perl (5.005_03), TclTk, Python, GNU programming
-tools, REBOL, wxWindows toolkit, the MinGW GNU C/C++ compiler, DJGPP
-GNU C/C++ compiler, Cint C interpreter, YaBasic.
-
-=back
-
For editors: if you're on Unix you probably have vi or a vi clone already,
and possibly an emacs too, so you may not need to download anything.
In any emacs the cperl-mode (M-x cperl-mode) gives you perhaps the
( http://www.textpad.com/ ) and UltraEdit
( http://www.ultraedit.com/ ), among others.
-If you are using Mac OS, the same concerns apply. MacPerl
+If you are using MacOS, the same concerns apply. MacPerl
(for Classic environments) comes with a simple editor.
Popular external editors are BBEdit ( http://www.bbedit.com/ )
-or Alpha ( http://www.kelehers.org/alpha/ ). Mac OS X users can
+or Alpha ( http://www.kelehers.org/alpha/ ). MacOS X users can
use Unix editors as well.
=over 4
=item MicroEMACS
-http://members.nbci.com/uemacs/
+http://www.microemacs.de/
=item XEmacs
http://www.xemacs.org/Download/index.html
+=item Jed
+
+http://space.mit.edu/~davis/jed/
+
=back
or a vi clone such as
=item Vile
-http://vile.cx/
+http://dickey.his.com/vile/vile.html
=item Vim
http://www.vim.org/
-win32: http://www.cs.vu.nl/%7Etmgil/vi.html
-
=back
For vi lovers in general, Windows or elsewhere:
that is distributed with the Tk module on CPAN. The ptkdb
( http://world.std.com/~aep/ptkdb/ ) is a Perl/tk based debugger that
acts as a development environment of sorts. Perl Composer
-( http://perlcomposer.sourceforge.net/vperl.html ) is an IDE for Perl/Tk
+( http://perlcomposer.sourceforge.net/ ) is an IDE for Perl/Tk
GUI creation.
In addition to an editor/IDE you might be interested in a more
The Curses module from CPAN provides a dynamically loadable object
module interface to a curses library. A small demo can be found at the
-directory http://www.cpan.org/authors/Tom_Christiansen/scripts/rep ;
+directory http://www.cpan.org/authors/Tom_Christiansen/scripts/rep.gz ;
this program repeats a command and updates the screen as needed, rendering
B<rep ps axu> similar to B<top>.
=back
-=head2 Is it unsafe to return a pointer to local data?
+=head2 Is it safe to return a reference to local or lexical data?
-No, Perl's garbage collection system takes care of this.
+Yes. Perl's garbage collection system takes care of this so
+everything works out right.
sub makeone {
my @a = ( 1 .. 10 );
of difficulty to people wanting to get at your code, but none can
definitively conceal it (true of every language, not just Perl).
+It is very easy to recover the source of Perl programs. You simply
+feed the program to the perl interpreter and use the modules in
+the B:: hierarchy. The B::Deparse module should be able to
+defeat most attempts to hide source. Again, this is not
+unique to Perl.
+
If you're concerned about people profiting from your code, then the
bottom line is that nothing but a restrictive license will give you
legal security. License your software and pepper it with threatening
=head1 NAME
-perlfaq4 - Data Manipulation ($Revision: 1.25 $, $Date: 2002/05/30 07:04:25 $)
+perlfaq4 - Data Manipulation ($Revision: 1.37 $, $Date: 2002/11/13 06:04:00 $)
=head1 DESCRIPTION
=head2 Why am I getting long decimals (eg, 19.9499999999999) instead of the numbers I should be getting (eg, 19.95)?
-The infinite set that a mathematician thinks of as the real numbers can
-only be approximated on a computer, since the computer only has a finite
-number of bits to store an infinite number of, um, numbers.
-
-Internally, your computer represents floating-point numbers in binary.
-Floating-point numbers read in from a file or appearing as literals
-in your program are converted from their decimal floating-point
-representation (eg, 19.95) to an internal binary representation.
-
-However, 19.95 can't be precisely represented as a binary
-floating-point number, just like 1/3 can't be exactly represented as a
-decimal floating-point number. The computer's binary representation
-of 19.95, therefore, isn't exactly 19.95.
-
-When a floating-point number gets printed, the binary floating-point
-representation is converted back to decimal. These decimal numbers
-are displayed in either the format you specify with printf(), or the
-current output format for numbers. (See L<perlvar/"$#"> if you use
-print. C<$#> has a different default value in Perl5 than it did in
-Perl4. Changing C<$#> yourself is deprecated.)
-
-This affects B<all> computer languages that represent decimal
-floating-point numbers in binary, not just Perl. Perl provides
-arbitrary-precision decimal numbers with the Math::BigFloat module
-(part of the standard Perl distribution), but mathematical operations
-are consequently slower.
-
-If precision is important, such as when dealing with money, it's good
-to work with integers and then divide at the last possible moment.
-For example, work in pennies (1995) instead of dollars and cents
-(19.95) and divide by 100 at the end.
-
-To get rid of the superfluous digits, just use a format (eg,
-C<printf("%.2f", 19.95)>) to get the required precision.
-See L<perlop/"Floating-point Arithmetic">.
+Internally, your computer represents floating-point numbers
+in binary. Digital (as in powers of two) computers cannot
+store all numbers exactly. Some real numbers lose precision
+in the process. This is a problem with how computers store
+numbers and affects all computer languages, not just Perl.
+L<perlnumber> show the gory details of number
+representations and conversions.
+
+To limit the number of decimal places in your numbers, you
+can use the printf or sprintf function. See the
+L<perlop|"Floating Point Arithmetic"> for more details.
+
+ printf "%.2f", 10/3;
+
+ my $number = sprintf "%.2f", 10/3;
+
=head2 Why isn't my octal data interpreted correctly?
-Perl only understands octal and hex numbers as such when they occur
-as literals in your program. Octal literals in perl must start with
-a leading "0" and hexadecimal literals must start with a leading "0x".
-If they are read in from somewhere and assigned, no automatic
-conversion takes place. You must explicitly use oct() or hex() if you
-want the values converted to decimal. oct() interprets
-both hex ("0x350") numbers and octal ones ("0350" or even without the
-leading "0", like "377"), while hex() only converts hexadecimal ones,
-with or without a leading "0x", like "0x255", "3A", "ff", or "deadbeef".
+Perl only understands octal and hex numbers as such when they occur as
+literals in your program. Octal literals in perl must start with a
+leading "0" and hexadecimal literals must start with a leading "0x".
+If they are read in from somewhere and assigned, no automatic
+conversion takes place. You must explicitly use oct() or hex() if you
+want the values converted to decimal. oct() interprets hex ("0x350"),
+octal ("0350" or even without the leading "0", like "377") and binary
+("0b1010") numbers, while hex() only converts hexadecimal ones, with
+or without a leading "0x", like "0x255", "3A", "ff", or "deadbeef".
The inverse mapping from decimal to octal can be done with either the
-"%o" or "%O" sprintf() formats. To get from decimal to hex try either
-the "%x" or the "%X" formats to sprintf().
+"%o" or "%O" sprintf() formats.
This problem shows up most often when people try using chmod(), mkdir(),
umask(), or sysopen(), which by widespread tradition typically take
(the number C<3> is treated as the bit pattern C<00000011>).
So, saying C<11 & 3> performs the "and" operation on numbers (yielding
-C<1>). Saying C<"11" & "3"> performs the "and" operation on strings
+C<3>). Saying C<"11" & "3"> performs the "and" operation on strings
(yielding C<"1">).
Most problems with C<&> and C<|> arise because the programmer thinks
If you're using a version of Perl before 5.004, you must call C<srand>
once at the start of your program to seed the random number generator.
+
+ BEGIN { srand() if $[ < 5.004 }
+
5.004 and later automatically call C<srand> at the beginning. Don't
-call C<srand> more than once--you make your numbers less random, rather
+call C<srand> more than once---you make your numbers less random, rather
than more.
Computers are good at being predictable and bad at being random
(despite appearances caused by bugs in your programs :-). see the
-F<random> artitcle in the "Far More Than You Ever Wanted To Know"
-collection in http://www.cpan.org/olddoc/FMTEYEWTK.tgz , courtesy of
+F<random> article in the "Far More Than You Ever Wanted To Know"
+collection in http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz , courtesy of
Tom Phoenix, talks more about this. John von Neumann said, ``Anyone
who attempts to generate random numbers by deterministic means is, of
course, living in a state of sin.''
return 1+int((((localtime(shift || time))[5] + 1899))/1000);
}
-On some systems, you'll find that the POSIX module's strftime() function
-has been extended in a non-standard way to use a C<%C> format, which they
-sometimes claim is the "century". It isn't, because on most such systems,
-this is only the first two digits of the four-digit year, and thus cannot
-be used to reliably determine the current century or millennium.
+You can also use the POSIX strftime() function which may be a bit
+slower but is easier to read and maintain.
+
+ use POSIX qw/strftime/;
+
+ my $week_of_the_year = strftime "%W", localtime;
+ my $day_of_the_year = strftime "%j", localtime;
+
+On some systems, the POSIX module's strftime() function has
+been extended in a non-standard way to use a C<%C> format,
+which they sometimes claim is the "century". It isn't,
+because on most such systems, this is only the first two
+digits of the four-digit year, and thus cannot be used to
+reliably determine the current century or millennium.
=head2 How can I compare two dates and find the difference?
=head2 How do I find yesterday's date?
-The C<time()> function returns the current time in seconds since the
-epoch. Take twenty-four hours off that:
+If you only need to find the date (and not the same time), you
+can use the Date::Calc module.
- $yesterday = time() - ( 24 * 60 * 60 );
+ use Date::Calc qw(Today Add_Delta_Days);
+
+ my @date = Add_Delta_Days( Today(), -1 );
+
+ print "@date\n";
-Then you can pass this to C<localtime()> and get the individual year,
-month, day, hour, minute, seconds values.
-
-Note very carefully that the code above assumes that your days are
-twenty-four hours each. For most people, there are two days a year
-when they aren't: the switch to and from summer time throws this off.
-A solution to this issue is offered by Russ Allbery.
+Most people try to use the time rather than the calendar to
+figure out dates, but that assumes that your days are
+twenty-four hours each. For most people, there are two days
+a year when they aren't: the switch to and from summer time
+throws this off. Russ Allbery offers this solution.
sub yesterday {
- my $now = defined $_[0] ? $_[0] : time;
- my $then = $now - 60 * 60 * 24;
- my $ndst = (localtime $now)[8] > 0;
- my $tdst = (localtime $then)[8] > 0;
- $then - ($tdst - $ndst) * 60 * 60;
- }
- # Should give you "this time yesterday" in seconds since epoch relative to
- # the first argument or the current time if no argument is given and
- # suitable for passing to localtime or whatever else you need to do with
- # it. $ndst is whether we're currently in daylight savings time; $tdst is
- # whether the point 24 hours ago was in daylight savings time. If $tdst
- # and $ndst are the same, a boundary wasn't crossed, and the correction
- # will subtract 0. If $tdst is 1 and $ndst is 0, subtract an hour more
- # from yesterday's time since we gained an extra hour while going off
- # daylight savings time. If $tdst is 0 and $ndst is 1, subtract a
- # negative hour (add an hour) to yesterday's time since we lost an hour.
- #
- # All of this is because during those days when one switches off or onto
- # DST, a "day" isn't 24 hours long; it's either 23 or 25.
- #
- # The explicit settings of $ndst and $tdst are necessary because localtime
- # only says it returns the system tm struct, and the system tm struct at
- # least on Solaris doesn't guarantee any particular positive value (like,
- # say, 1) for isdst, just a positive value. And that value can
- # potentially be negative, if DST information isn't available (this sub
- # just treats those cases like no DST).
- #
- # Note that between 2am and 3am on the day after the time zone switches
- # off daylight savings time, the exact hour of "yesterday" corresponding
- # to the current hour is not clearly defined. Note also that if used
- # between 2am and 3am the day after the change to daylight savings time,
- # the result will be between 3am and 4am of the previous day; it's
- # arguable whether this is correct.
- #
- # This sub does not attempt to deal with leap seconds (most things don't).
- #
- # Copyright relinquished 1999 by Russ Allbery <rra@stanford.edu>
- # This code is in the public domain
+ my $now = defined $_[0] ? $_[0] : time;
+ my $then = $now - 60 * 60 * 24;
+ my $ndst = (localtime $now)[8] > 0;
+ my $tdst = (localtime $then)[8] > 0;
+ $then - ($tdst - $ndst) * 60 * 60;
+ }
+
+Should give you "this time yesterday" in seconds since epoch relative to
+the first argument or the current time if no argument is given and
+suitable for passing to localtime or whatever else you need to do with
+it. $ndst is whether we're currently in daylight savings time; $tdst is
+whether the point 24 hours ago was in daylight savings time. If $tdst
+and $ndst are the same, a boundary wasn't crossed, and the correction
+will subtract 0. If $tdst is 1 and $ndst is 0, subtract an hour more
+from yesterday's time since we gained an extra hour while going off
+daylight savings time. If $tdst is 0 and $ndst is 1, subtract a
+negative hour (add an hour) to yesterday's time since we lost an hour.
+
+All of this is because during those days when one switches off or onto
+DST, a "day" isn't 24 hours long; it's either 23 or 25.
+
+The explicit settings of $ndst and $tdst are necessary because localtime
+only says it returns the system tm struct, and the system tm struct at
+least on Solaris doesn't guarantee any particular positive value (like,
+say, 1) for isdst, just a positive value. And that value can
+potentially be negative, if DST information isn't available (this sub
+just treats those cases like no DST).
+
+Note that between 2am and 3am on the day after the time zone switches
+off daylight savings time, the exact hour of "yesterday" corresponding
+to the current hour is not clearly defined. Note also that if used
+between 2am and 3am the day after the change to daylight savings time,
+the result will be between 3am and 4am of the previous day; it's
+arguable whether this is correct.
+
+This sub does not attempt to deal with leap seconds (most things don't).
+
+
=head2 Does Perl have a Year 2000 problem? Is Perl Y2K compliant?
print "My sub returned @{[mysub(1,2,3)]} that time.\n";
-If you prefer scalar context, similar chicanery is also useful for
-arbitrary expressions:
-
- print "That yields ${\($n + 5)} widgets\n";
-
-Version 5.004 of Perl had a bug that gave list context to the
-expression in C<${...}>, but this is fixed in version 5.005.
-
See also ``How can I expand variables in text strings?'' in this
section of the FAQ.
See the documentation for Text::Autoformat to appreciate its many
capabilities.
-=head2 How can I access/change the first N letters of a string?
-
-There are many ways. If you just want to grab a copy, use
-substr():
+=head2 How can I access or change N characters of a string?
- $first_byte = substr($a, 0, 1);
+You can access the first characters of a string with substr().
+To get the first character, for example, start at position 0
+and grab the string of length 1.
-If you want to modify part of a string, the simplest way is often to
-use substr() as an lvalue:
- substr($a, 0, 3) = "Tom";
+ $string = "Just another Perl Hacker";
+ $first_char = substr( $string, 0, 1 ); # 'J'
-Although those with a pattern matching kind of thought process will
-likely prefer
+To change part of a string, you can use the optional fourth
+argument which is the replacement string.
- $a =~ s/^.../Tom/;
+ substr( $string, 13, 4, "Perl 5.8.0" );
+
+You can also use substr() as an lvalue.
+ substr( $string, 13, 4 ) = "Perl 5.8.0";
+
=head2 How do I change the Nth occurrence of something?
You have to keep track of N yourself. For example, let's say you want
capitalization of the movie I<Dr. Strangelove or: How I Learned to
Stop Worrying and Love the Bomb>, for example.
-=head2 How can I split a [character] delimited string except when inside
-[character]? (Comma-separated files)
+=head2 How can I split a [character] delimited string except when inside [character]?
-Take the example case of trying to split a string that is comma-separated
-into its different fields. (We'll pretend you said comma-separated, not
-comma-delimited, which is different and almost never what you mean.) You
-can't use C<split(/,/)> because you shouldn't split if the comma is inside
-quotes. For example, take a data line like this:
+Several modules can handle this sort of pasing---Text::Balanced,
+Text::CVS, Text::CVS_XS, and Text::ParseWords, among others.
+
+Take the example case of trying to split a string that is
+comma-separated into its different fields. You can't use C<split(/,/)>
+because you shouldn't split if the comma is inside quotes. For
+example, take a data line like this:
SAR001,"","Cimetrix, Inc","Bob Smith","CAM",N,8,1,0,7,"Error, Core Dumped"
Due to the restriction of the quotes, this is a fairly complex
-problem. Thankfully, we have Jeffrey Friedl, author of a highly
-recommended book on regular expressions, to handle these for us. He
+problem. Thankfully, we have Jeffrey Friedl, author of
+I<Mastering Regular Expressions>, to handle these for us. He
suggests (assuming your string is contained in $text):
@new = ();
If you want to represent quotation marks inside a
quotation-mark-delimited field, escape them with backslashes (eg,
-C<"like \"this\"">. Unescaping them is a task addressed earlier in
-this section.
+C<"like \"this\"">.
Alternatively, the Text::ParseWords module (part of the standard Perl
distribution) lets you say:
=head2 How do I find the first array element for which a condition is true?
-You can use this if you care about the index:
-
- for ($i= 0; $i < @array; $i++) {
- if ($array[$i] eq "Waldo") {
- $found_index = $i;
- last;
+To find the first array element which satisfies a condition, you can
+use the first() function in the List::Util module, which comes with
+Perl 5.8. This example finds the first element that contains "Perl".
+
+ use List::Util qw(first);
+
+ my $element = first { /Perl/ } @array;
+
+If you cannot use List::Util, you can make your own loop to do the
+same thing. Once you find the element, you stop the loop with last.
+
+ my $found;
+ foreach my $element ( @array )
+ {
+ if( /Perl/ ) { $found = $element; last }
+ }
+
+If you want the array index, you can iterate through the indices
+and check the array element at each index until you find one
+that satisfies the condition.
+
+ my( $found, $i ) = ( undef, -1 );
+ for( $i = 0; $i < @array; $i++ )
+ {
+ if( $array[$i] =~ /Perl/ )
+ {
+ $found = $array[$i];
+ $index = $i;
+ last;
+ }
}
- }
-
-Now C<$found_index> has what you want.
=head2 How do I handle linked lists?
$_ **= 3;
$_ *= (4/3) * 3.14159; # this will be constant folded
}
+
+which can also be done with map() which is made to transform
+one list into another:
+
+ @volumes = map {$_ ** 3 * (4/3) * 3.14159} @radii;
If you want to do the same thing to modify the values of the
hash, you can use the C<values> function. As of Perl 5.6
=head2 How do I permute N elements of a list?
-Here's a little program that generates all permutations
-of all the words on each line of input. The algorithm embodied
-in the permute() function should work on any list:
-
- #!/usr/bin/perl -n
- # tsc-permute: permute each word of input
- permute([split], []);
- sub permute {
- my @items = @{ $_[0] };
- my @perms = @{ $_[1] };
- unless (@items) {
- print "@perms\n";
- } else {
- my(@newitems,@newperms,$i);
- foreach $i (0 .. $#items) {
- @newitems = @items;
- @newperms = @perms;
- unshift(@newperms, splice(@newitems, $i, 1));
- permute([@newitems], [@newperms]);
- }
+Use the List::Permutor module on CPAN. If the list is
+actually an array, try the Algorithm::Permute module (also
+on CPAN). It's written in XS code and is very efficient.
+
+ use Algorithm::Permute;
+ my @array = 'a'..'d';
+ my $p_iterator = Algorithm::Permute->new ( \@array );
+ while (my @perm = $p_iterator->next) {
+ print "next permutation: (@perm)\n";
+ }
+
+Here's a little program that generates all permutations of
+all the words on each line of input. The algorithm embodied
+in the permute() function is discussed in Volume 4 (still
+unpublished) of Knuth's I<The Art of Computer Programming>
+and will work on any list:
+
+ #!/usr/bin/perl -n
+ # Fischer-Kause ordered permutation generator
+
+ sub permute (&@) {
+ my $code = shift;
+ my @idx = 0..$#_;
+ while ( $code->(@_[@idx]) ) {
+ my $p = $#idx;
+ --$p while $idx[$p-1] > $idx[$p];
+ my $q = $p or return;
+ push @idx, reverse splice @idx, $p;
+ ++$q while $idx[$p-1] > $idx[$q];
+ @idx[$p-1,$q]=@idx[$q,$p-1];
+ }
}
- }
-Unfortunately, this algorithm is very inefficient. The Algorithm::Permute
-module from CPAN runs at least an order of magnitude faster. If you don't
-have a C compiler (or a binary distribution of Algorithm::Permute), then
-you can use List::Permutor which is written in pure Perl, and is still
-several times faster than the algorithm above.
+ permute {print"@_\n"} split;
=head2 How do I sort an array by (anything)?
above.
See the F<sort> artitcle article in the "Far More Than You Ever Wanted
-To Know" collection in http://www.cpan.org/olddoc/FMTEYEWTK.tgz for
+To Know" collection in http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz for
more about this approach.
See also the question below on sorting hashes.
Use the Tie::IxHash from CPAN.
use Tie::IxHash;
- tie(%myhash, Tie::IxHash);
- for ($i=0; $i<20; $i++) {
+ tie my %myhash, Tie::IxHash;
+ for (my $i=0; $i<20; $i++) {
$myhash{$i} = 2*$i;
}
- @keys = keys %myhash;
+ my @keys = keys %myhash;
# @keys = (0,1,2,3,...)
=head2 Why does passing a subroutine an undefined element in a hash create it?
On less elegant (read: Byzantine) systems, however, you have
to play tedious games with "text" versus "binary" files. See
-L<perlfunc/"binmode"> or L<perlopentut>. Most of these ancient-thinking
-systems are curses out of Microsoft, who seem to be committed to putting
-the backward into backward compatibility.
+L<perlfunc/"binmode"> or L<perlopentut>.
If you're concerned about 8-bit ASCII data, then see L<perllocale>.
=head1 NAME
-perlfaq5 - Files and Formats ($Revision: 1.18 $, $Date: 2002/05/30 07:04:25 $)
+perlfaq5 - Files and Formats ($Revision: 1.26 $, $Date: 2002/09/21 21:04:17 $)
=head1 DESCRIPTION
=head2 How can I output my numbers with commas added?
-This one from Benjamin Goldberg will do it for you:
+This subroutine will add commas to your number:
+
+ sub commify {
+ local $_ = shift;
+ 1 while s/^([-+]?\d+)(\d{3})/$1,$2/;
+ return $_;
+ }
+
+This regex from Benjamin Goldberg will add commas to numbers:
s/(^[-+]?\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d))/$1,/g;
-or written verbosely:
+It is easier to see with comments:
s/(
^[-+]? # beginning of number.
=head2 How can I reliably rename a file?
-If your operating system supports a proper mv(1) utility or its functional
-equivalent, this works:
+If your operating system supports a proper mv(1) utility or its
+functional equivalent, this works:
rename($old, $new) or system("mv", $old, $new);
=head2 How do I print to more than one file at once?
-If you only have to do this once, you can do this:
-
- for $fh (FH1, FH2, FH3) { print $fh "whatever\n" }
-
-To connect up to one filehandle to several output filehandles, it's
-easiest to use the tee(1) program if you have it, and let it take care
-of the multiplexing:
+To connect one filehandle to several output filehandles,
+you can use the IO::Tee or Tie::FileHandle::Multiplex modules.
- open (FH, "| tee file1 file2 file3");
+If you only have to do this once, you can print individually
+to each filehandle.
-Or even:
+ for $fh (FH1, FH2, FH3) { print $fh "whatever\n" }
- # make STDOUT go to three files, plus original STDOUT
- open (STDOUT, "| tee file1 file2 file3") or die "Teeing off: $!\n";
- print "whatever\n" or die "Writing: $!\n";
- close(STDOUT) or die "Closing: $!\n";
+=head2 How can I read in an entire file all at once?
-Otherwise you'll have to write your own multiplexing print
-function--or your own tee program--or use Tom Christiansen's,
-at http://www.cpan.org/authors/id/TOMC/scripts/tct.gz , which is
-written in Perl and offers much greater functionality
-than the stock version.
+You can use the File::Slurp module to do it in one step.
-=head2 How can I read in an entire file all at once?
+ use File::Slurp;
+
+ $all_of_it = read_file($filename); # entire file in scalar
+ @all_lines = read_file($filename); # one line perl element
The customary Perl approach for processing all the lines in a file is to
do so one line at a time:
This is elaborately and painstakingly described in the
F<file-dir-perms> article in the "Far More Than You Ever Wanted To
-Know" collection in http://www.cpan.org/olddoc/FMTEYEWTK.tgz .
+Know" collection in http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz .
The executive summary: learn how your filesystem works. The
permissions on a file say what can happen to the data in that file.
srand;
rand($.) < 1 && ($line = $_) while <>;
-This has a significant advantage in space over reading the whole
-file in. A simple proof by induction is available upon
-request if you doubt the algorithm's correctness.
+This has a significant advantage in space over reading the whole file
+in. You can find a proof of this method in I<The Art of Computer
+Programming>, Volume 2, Section 3.4.2, by Donald E. Knuth.
+
+You can use the File::Random module which provides a function
+for that algorithm:
+
+ use File::Random qw/random_line/;
+ my $line = random_line($filename);
+
+Another way is to use the Tie::File module, which treats the entire
+file as an array. Simply access a random array element.
=head2 Why do I get weird spaces when I print an array of lines?
=head1 NAME
-perlfaq6 - Regular Expressions ($Revision: 1.12 $, $Date: 2002/06/01 22:31:09 $)
+perlfaq6 - Regular Expressions ($Revision: 1.18 $, $Date: 2002/10/30 18:44:21 $)
=head1 DESCRIPTION
=head2 I put a regular expression into $/ but it didn't work. What's wrong?
-$/ must be a string, not a regular expression. Awk has to be better
-for something. :-)
+As of Perl 5.8.0, $/ has to be a string. This may change in 5.10,
+but don't get your hopes up. Until then, you can use these examples
+if you really need to do this.
+
+Use the four argument form of sysread to continually add to
+a buffer. After you add to the buffer, you check if you have a
+complete line (using your regular expression).
+
+ local $_ = "";
+ while( sysread FH, $_, 8192, length ) {
+ while( s/^((?s).*?)your_pattern/ ) {
+ my $record = $1;
+ # do stuff here.
+ }
+ }
+
+ You can do the same thing with foreach and a match using the
+ c flag and the \G anchor, if you do not mind your entire file
+ being in memory at the end.
+
+ local $_ = "";
+ while( sysread FH, $_, 8192, length ) {
+ foreach my $record ( m/\G((?s).*?)your_pattern/gc ) {
+ # do stuff here.
+ }
+ substr( $_, 0, pos ) = "" if pos;
+ }
-Actually, you could do this if you don't mind reading the whole file
-into memory:
-
- undef $/;
- @records = split /your_pattern/, <FH>;
-
-The Net::Telnet module (available from CPAN) has the capability to
-wait for a pattern in the input stream, or timeout if it doesn't
-appear within a certain time.
-
- ## Create a file with three lines.
- open FH, ">file";
- print FH "The first line\nThe second line\nThe third line\n";
- close FH;
-
- ## Get a read/write filehandle to it.
- $fh = new IO::File "+<file";
-
- ## Attach it to a "stream" object.
- use Net::Telnet;
- $file = new Net::Telnet (-fhopen => $fh);
-
- ## Search for the second line and print out the third.
- $file->waitfor('/second line\n/');
- print $file->getline;
=head2 How do I substitute case insensitively on the LHS while preserving case on the RHS?
=head2 How can I make C<\w> match national character sets?
-See L<perllocale>.
+Put C<use locale;> in your script. The \w character class is taken
+from the current locale.
+
+See L<perllocale> for details.
=head2 How can I match a locale-smart version of C</[a-zA-Z]/>?
-One alphabetic character would be C</[^\W\d_]/>, no matter what locale
-you're in. Non-alphabetics would be C</[\W\d_]/> (assuming you don't
-consider an underscore a letter).
+You can use the POSIX character class syntax C</[[:alpha:]]/>
+documented in L<perlre>.
+
+No matter which locale you are in, the alphabetic characters are
+the characters in \w without the digits and the underscore.
+As a regex, that looks like C</[^\W\d_]/>. Its complement,
+the non-alphabetics, is then everything in \W along with
+the digits and the underscore, or C</[\W\d_]/>.
=head2 How can I quote a variable to use in a regex?
=head2 What good is C<\G> in a regular expression?
-The notation C<\G> is used in a match or substitution in conjunction with
-the C</g> modifier to anchor the regular expression to the point just past
-where the last match occurred, i.e. the pos() point. A failed match resets
-the position of C<\G> unless the C</c> modifier is in effect. C<\G> can be
-used in a match without the C</g> modifier; it acts the same (i.e. still
-anchors at the pos() point) but of course only matches once and does not
-update pos(), as non-C</g> expressions never do. C<\G> in an expression
-applied to a target string that has never been matched against a C</g>
-expression before or has had its pos() reset is functionally equivalent to
-C<\A>, which matches at the beginning of the string.
-
-For example, suppose you had a line of text quoted in standard mail
-and Usenet notation, (that is, with leading C<< > >> characters), and
-you want change each leading C<< > >> into a corresponding C<:>. You
-could do so in this way:
-
- s/^(>+)/':' x length($1)/gem;
-
-Or, using C<\G>, the much simpler (and faster):
-
- s/\G>/:/g;
-
-A more sophisticated use might involve a tokenizer. The following
-lex-like example is courtesy of Jeffrey Friedl. It did not work in
-5.003 due to bugs in that release, but does work in 5.004 or better.
-(Note the use of C</c>, which prevents a failed match with C</g> from
-resetting the search position back to the beginning of the string.)
+You use the C<\G> anchor to start the next match on the same
+string where the last match left off. The regular
+expression engine cannot skip over any characters to find
+the next match with this anchor, so C<\G> is similar to the
+beginning of string anchor, C<^>. The C<\G> anchor is typically
+used with the C<g> flag. It uses the value of pos()
+as the position to start the next match. As the match
+operator makes successive matches, it updates pos() with the
+position of the next character past the last match (or the
+first character of the next match, depending on how you like
+to look at it). Each string has its own pos() value.
+
+Suppose you want to match all of consective pairs of digits
+in a string like "1122a44" and stop matching when you
+encounter non-digits. You want to match C<11> and C<22> but
+the letter <a> shows up between C<22> and C<44> and you want
+to stop at C<a>. Simply matching pairs of digits skips over
+the C<a> and still matches C<44>.
+
+ $_ = "1122a44";
+ my @pairs = m/(\d\d)/g; # qw( 11 22 44 )
+
+If you use the \G anchor, you force the match after C<22> to
+start with the C<a>. The regular expression cannot match
+there since it does not find a digit, so the next match
+fails and the match operator returns the pairs it already
+found.
+
+ $_ = "1122a44";
+ my @pairs = m/\G(\d\d)/g; # qw( 11 22 )
+
+You can also use the C<\G> anchor in scalar context. You
+still need the C<g> flag.
+
+ $_ = "1122a44";
+ while( m/\G(\d\d)/g )
+ {
+ print "Found $1\n";
+ }
+
+After the match fails at the letter C<a>, perl resets pos()
+and the next match on the same string starts at the beginning.
+
+ $_ = "1122a44";
+ while( m/\G(\d\d)/g )
+ {
+ print "Found $1\n";
+ }
+
+ print "Found $1 after while" if m/(\d\d)/g; # finds "11"
+
+You can disable pos() resets on fail with the C<c> flag.
+Subsequent matches start where the last successful match
+ended (the value of pos()) even if a match on the same
+string as failed in the meantime. In this case, the match
+after the while() loop starts at the C<a> (where the last
+match stopped), and since it does not use any anchor it can
+skip over the C<a> to find "44".
+
+ $_ = "1122a44";
+ while( m/\G(\d\d)/gc )
+ {
+ print "Found $1\n";
+ }
+
+ print "Found $1 after while" if m/(\d\d)/g; # finds "44"
+
+Typically you use the C<\G> anchor with the C<c> flag
+when you want to try a different match if one fails,
+such as in a tokenizer. Jeffrey Friedl offers this example
+which works in 5.004 or later.
while (<>) {
chomp;
PARSER: {
- m/ \G( \d+\b )/gcx && do { print "number: $1\n"; redo; };
- m/ \G( \w+ )/gcx && do { print "word: $1\n"; redo; };
- m/ \G( \s+ )/gcx && do { print "space: $1\n"; redo; };
- m/ \G( [^\w\d]+ )/gcx && do { print "other: $1\n"; redo; };
+ m/ \G( \d+\b )/gcx && do { print "number: $1\n"; redo; };
+ m/ \G( \w+ )/gcx && do { print "word: $1\n"; redo; };
+ m/ \G( \s+ )/gcx && do { print "space: $1\n"; redo; };
+ m/ \G( [^\w\d]+ )/gcx && do { print "other: $1\n"; redo; };
}
}
-Of course, that could have been written as
-
- while (<>) {
- chomp;
- PARSER: {
- if ( /\G( \d+\b )/gcx {
- print "number: $1\n";
- redo PARSER;
- }
- if ( /\G( \w+ )/gcx {
- print "word: $1\n";
- redo PARSER;
- }
- if ( /\G( \s+ )/gcx {
- print "space: $1\n";
- redo PARSER;
- }
- if ( /\G( [^\w\d]+ )/gcx {
- print "other: $1\n";
- redo PARSER;
- }
- }
- }
-
-but then you lose the vertical alignment of the regular expressions.
+For each line, the PARSER loop first tries to match a series
+of digits followed by a word boundary. This match has to
+start at the place the last match left off (or the beginning
+of the string on the first match). Since C<m/ \G( \d+\b
+)/gcx> uses the C<c> flag, if the string does not match that
+regular expression, perl does not reset pos() and the next
+match starts at the same position to try a different
+pattern.
=head2 Are Perl regexes DFAs or NFAs? Are they POSIX compliant?
Here are a few ways, all painful, to deal with it:
- $martian =~ s/([A-Z][A-Z])/ $1 /g; # Make sure adjacent ``martian'' bytes
- # are no longer adjacent.
+ $martian =~ s/([A-Z][A-Z])/ $1 /g; # Make sure adjacent ``martian''
+ # bytes are no longer adjacent.
print "found GX!\n" if $martian =~ /GX/;
Or like this:
print "found GX!\n", last if $1 eq 'GX';
}
-Or like this:
-
- die "sorry, Perl doesn't (yet) have Martian support )-:\n";
-
-There are many double- (and multi-) byte encodings commonly used these
-days. Some versions of these have 1-, 2-, 3-, and 4-byte characters,
-all mixed.
+Here's another, slightly less painful, way to do it from Benjamin
+Goldberg:
+
+ $martian =~ m/
+ (?!<[A-Z])
+ (?:[A-Z][A-Z])*?
+ GX
+ /x;
+
+This succeeds if the "martian" character GX is in the string, and fails
+otherwise. If you don't like using (?!<), you can replace (?!<[A-Z])
+with (?:^|[^A-Z]).
+
+It does have the drawback of putting the wrong thing in $-[0] and $+[0],
+but this usually can be worked around.
=head2 How do I match a pattern that is supplied by the user?
=head1 NAME
-perlfaq7 - General Perl Language Issues ($Revision: 1.8 $, $Date: 2002/03/26 15:48:32 $)
+perlfaq7 - General Perl Language Issues ($Revision: 1.11 $, $Date: 2002/11/10 17:35:47 $)
=head1 DESCRIPTION
Another way is to use undef as an element on the left-hand-side:
($dev, $ino, undef, undef, $uid, $gid) = stat($file);
+
+You can also use a list slice to select only the elements that
+you need:
+
+ ($dev, $ino, $uid, $gid) = ( stat($file) )[0,1,4,5];
=head2 How do I temporarily block warnings?
=item Passing Filehandles
-To pass filehandles to subroutines, use the C<*FH> or C<\*FH> notations.
+As of Perl 5.6, you can represent filehandles with scalar variables
+which you treat as any other scalar.
+
+ open my $fh, $filename or die "Cannot open $filename! $!";
+ func( $fh );
+
+ sub func {
+ my $passed_fh = shift;
+
+ my $line = <$fh>;
+ }
+
+Before Perl 5.6, you had to use the C<*FH> or C<\*FH> notations.
These are "typeglobs"--see L<perldata/"Typeglobs and Filehandles">
and especially L<perlsub/"Pass by Reference"> for more information.
-Here's an excerpt:
-
-If you're passing around filehandles, you could usually just use the bare
-typeglob, like *STDOUT, but typeglobs references would be better because
-they'll still work properly under C<use strict 'refs'>. For example:
-
- splutter(\*STDOUT);
- sub splutter {
- my $fh = shift;
- print $fh "her um well a hmmm\n";
- }
-
- $rec = get_rec(\*STDIN);
- sub get_rec {
- my $fh = shift;
- return scalar <$fh>;
- }
-
-If you're planning on generating new filehandles, you could do this:
-
- sub openit {
- my $path = shift;
- local *FH;
- return open (FH, $path) ? *FH : undef;
- }
- $fh = openit('< /etc/motd');
- print <$fh>;
-
=item Passing Regexes
To pass regexes around, you'll need to be using a release of Perl
=head2 How can I access a dynamic variable while a similarly named lexical is in scope?
-You can do this via symbolic references, provided you haven't set
-C<use strict "refs">. So instead of $var, use C<${'var'}>.
+If you know your package, you can just mention it explicitly, as in
+$Some_Pack::var. Note that the notation $::var is B<not> the dynamic $var
+in the current package, but rather the one in the "main" package, as
+though you had written $main::var.
+
+ use vars '$var';
+ local $var = "global";
+ my $var = "lexical";
- local $var = "global";
- my $var = "lexical";
+ print "lexical is $var\n";
+ print "global is $main::var\n";
- print "lexical is $var\n";
+Alternatively you can use the compiler directive our() to bring a
+dynamic variable into the current lexical scope.
- no strict 'refs';
- print "global is ${'var'}\n";
+ require 5.006; # our() did not exist before 5.6
+ use vars '$var';
-If you know your package, you can just mention it explicitly, as in
-$Some_Pack::var. Note that the notation $::var is I<not> the dynamic
-$var in the current package, but rather the one in the C<main>
-package, as though you had written $main::var. Specifying the package
-directly makes you hard-code its name, but it executes faster and
-avoids running afoul of C<use strict "refs">.
+ local $var = "global";
+ my $var = "lexical";
+
+ print "lexical is $var\n";
+
+ {
+ our $var;
+ print "global is $var\n";
+ }
=head2 What's the difference between deep and shallow binding?
print "No such command: $string\n";
}
-=head2 How can I catch accesses to undefined variables/functions/methods?
+=head2 How can I catch accesses to undefined variables, functions, or methods?
The AUTOLOAD method, discussed in L<perlsub/"Autoloading"> and
L<perltoot/"AUTOLOAD: Proxy Methods">, lets you capture calls to
undefined functions and methods.
When it comes to undefined variables that would trigger a warning
-under C<-w>, you can use a handler to trap the pseudo-signal
-C<__WARN__> like this:
-
- $SIG{__WARN__} = sub {
-
- for ( $_[0] ) { # voici un switch statement
-
- /Use of uninitialized value/ && do {
- # promote warning to a fatal
- die $_;
- };
-
- # other warning cases to catch could go here;
-
- warn $_;
- }
+under C<use warnings>, you can promote the warning to an error.
- };
+ use warnings FATAL => qw(uninitialized);
=head2 Why can't a method included in this same file be found?
=head1 NAME
-perlfaq8 - System Interaction ($Revision: 1.8 $, $Date: 2002/05/16 12:41:42 $)
+perlfaq8 - System Interaction ($Revision: 1.14 $, $Date: 2002/11/10 17:35:47 $)
=head1 DESCRIPTION
=head2 How do I start a process in the background?
-You could use
+Several modules can start other processes that do not block
+your Perl program. You can use IPC::Open3, Parallel::Jobs,
+IPC::Run, and some of the POE modules. See CPAN for more
+details.
+
+You could also use
system("cmd &")
=item Zombies
-You have to be prepared to "reap" the child process when it finishes
+You have to be prepared to "reap" the child process when it finishes.
$SIG{CHLD} = sub { wait };
+
+ $SIG{CHLD} = 'IGNORE';
+
+You can also use a double fork. You immediately wait() for your
+first child, and the init daemon will wait() for your grandchild once
+it exits.
+
+ unless ($pid = fork) {
+ unless (fork) {
+ exec "what you really wanna do";
+ die "exec failed!";
+ }
+ exit 0;
+ }
+ waitpid($pid,0);
+
See L<perlipc/"Signals"> for other examples of code to do this.
Zombies are not an issue with C<system("prog &")>.
script's STDOUT and STDERR, unless the system() command redirects them.
Backticks and open() read B<only> the STDOUT of your command.
+You can also use the open3() function from IPC::Open3. Benjamin
+Goldberg provides some sample code:
+
+To capture a program's STDOUT, but discard its STDERR:
+
+ use IPC::Open3;
+ use File::Spec;
+ use Symbol qw(gensym);
+ open(NULL, ">", File::Spec->devnull);
+ my $pid = open3(gensym, \*PH, ">&NULL", "cmd");
+ while( <PH> ) { }
+ waitpid($pid, 0);
+
+To capture a program's STDERR, but discard its STDOUT:
+
+ use IPC::Open3;
+ use File::Spec;
+ use Symbol qw(gensym);
+ open(NULL, ">", File::Spec->devnull);
+ my $pid = open3(gensym, ">&NULL", \*PH, "cmd");
+ while( <PH> ) { }
+ waitpid($pid, 0);
+
+To capture a program's STDERR, and let its STDOUT go to our own STDERR:
+
+ use IPC::Open3;
+ use Symbol qw(gensym);
+ my $pid = open3(gensym, ">&STDERR", \*PH, "cmd");
+ while( <PH> ) { }
+ waitpid($pid, 0);
+
+To read both a command's STDOUT and its STDERR separately, you can
+redirect them to temp files, let the command run, then read the temp
+files:
+
+ use IPC::Open3;
+ use Symbol qw(gensym);
+ use IO::File;
+ local *CATCHOUT = IO::File->new_tempfile;
+ local *CATCHERR = IO::File->new_tempfile;
+ my $pid = open3(gensym, ">&CATCHOUT", ">&CATCHERR", "cmd");
+ waitpid($pid, 0);
+ seek $_, 0, 0 for \*CATCHOUT, \*CATCHERR;
+ while( <CATCHOUT> ) {}
+ while( <CATCHERR> ) {}
+
+But there's no real need for *both* to be tempfiles... the following
+should work just as well, without deadlocking:
+
+ use IPC::Open3;
+ use Symbol qw(gensym);
+ use IO::File;
+ local *CATCHERR = IO::File->new_tempfile;
+ my $pid = open3(gensym, \*CATCHOUT, ">&CATCHERR", "cmd");
+ while( <CATCHOUT> ) {}
+ waitpid($pid, 0);
+ seek CATCHERR, 0, 0;
+ while( <CATCHERR> ) {}
+
+And it'll be faster, too, since we can begin processing the program's
+stdout immediately, rather than waiting for the program to finish.
+
With any of these, you can change file descriptors before the call:
open(STDOUT, ">logfile");
backticks, not csh(1)! Details on why Perl's system() and backtick
and pipe opens all use the Bourne shell are in the
F<versus/csh.whynot> article in the "Far More Than You Ever Wanted To
-Know" collection in http://www.cpan.org/olddoc/FMTEYEWTK.tgz . To
+Know" collection in http://www.cpan.org/misc/olddoc/FMTEYEWTK.tgz . To
capture a command's STDERR and STDOUT together:
$output = `cmd 2>&1`; # either with backticks
=head2 Why doesn't open() return an error when a pipe open fails?
-If the second argument to a piped C<open> contains shell
+If the second argument to a piped open() contains shell
metacharacters, perl fork()s, then exec()s a shell to decode the
metacharacters and eventually run the desired program. If the program
couldn't be run, it's the shell that gets the message, not Perl. All
successfully started. You can still capture the shell's STDERR and
check it for error messages. See L<"How can I capture STDERR from an
external command?"> elsewhere in this document, or use the
-L<IPC::Open3> module.
+IPC::Open3 module.
-If there are no shell metacharacters in the argument of C<open>, Perl
+If there are no shell metacharacters in the argument of open(), Perl
runs the command directly, without using the shell, and can correctly
report whether the command started.
=head2 How can I call backticks without shell processing?
-This is a bit tricky. Instead of writing
+This is a bit tricky. You can't simply write the command
+like this:
@ok = `grep @opts '$search_string' @filenames`;
-You have to do this:
+As of Perl 5.8.0, you can use open() with multiple arguments.
+Just like the list forms of system() and exec(), no shell
+escapes happen.
+
+ open( GREP, "-|", 'grep', @opts, $search_string, @filenames );
+ chomp(@ok = <GREP>);
+ close GREP;
+
+You can also:
my @ok = ();
if (open(GREP, "-|")) {
Just as with system(), no shell escapes happen when you exec() a list.
Further examples of this can be found in L<perlipc/"Safe Pipe Opens">.
-Note that if you're stuck on Microsoft, no solution to this vexing issue
+Note that if you're use Microsoft, no solution to this vexing issue
is even possible. Even if Perl were to emulate fork(), you'd still
-be hosed, because Microsoft gives no argc/argv-style API. Their API
-always reparses from a single string, which is fundamentally wrong,
-but you're not likely to get the Gods of Redmond to acknowledge this
-and fix it for you.
+be stuck, because Microsoft does not have a argc/argv-style API.
=head2 Why can't my script read from STDIN after I gave it EOF (^D on Unix, ^Z on MS-DOS)?
``Signals'' in the Camel. You may instead use the more flexible
Sys::AlarmCall module available from CPAN.
+The alarm() function is not implemented on all versions of Windows.
+Check the documentation for your specific version of Perl.
+
=head2 How do I set CPU limits?
Use the BSD::Resource module from CPAN.
Use the reaper code from L<perlipc/"Signals"> to call wait() when a
SIGCHLD is received, or else use the double-fork technique described
-in L<perlfunc/fork>.
+in L<perlfaq8/"How do I start a process in the background?">.
=head2 How do I use an SQL database?
There are a number of excellent interfaces to SQL databases. See the
-DBD::* modules available from http://www.cpan.org/modules/DBD .
+DBD::* modules available from http://www.cpan.org/modules/by-module/DBD/ .
A lot of information on this can be found at http://dbi.perl.org/
=head2 How do I make a system() exit on control-C?
=head1 NAME
-perlfaq9 - Networking ($Revision: 1.9 $, $Date: 2002/04/07 18:46:13 $)
+perlfaq9 - Networking ($Revision: 1.13 $, $Date: 2002/11/13 06:07:58 $)
=head1 DESCRIPTION
C<HTML::SimpleLinkExtor> as an example for something specifically
suited to your needs.
+You can use URI::Find to extract URLs from an arbitrary text document.
+
Less complete solutions involving regular expressions can save
you a lot of processing time if you know that the input is simple. One
solution from Tom Christiansen runs 100 times faster than most
=head2 How do I download a file from the user's machine? How do I open a file on another machine?
-In the context of an HTML form, you can use what's known as
-B<multipart/form-data> encoding. The CGI.pm module (available from
-CPAN) supports this in the start_multipart_form() method, which isn't
-the same as the startform() method.
+In this case, download means to use the file upload feature of HTML
+forms. You allow the web surfer to specify a file to send to your web
+server. To you it looks like a download, and to the user it looks
+like an upload. No matter what you call it, you do it with what's
+known as B<multipart/form-data> encoding. The CGI.pm module (which
+comes with Perl as part of the Standard Library) supports this in the
+start_multipart_form() method, which isn't the same as the startform()
+method.
+
+See the section in the CGI.pm documentation on file uploads for code
+examples and details.
=head2 How do I make a pop-up menu in HTML?
=head2 How do I put a password on my web pages?
-That depends. You'll need to read the documentation for your web
-server, or perhaps check some of the other FAQs referenced above.
+To enable authentication for your web server, you need to configure
+your web server. The configuration is different for different sorts
+of web servers---apache does it differently from iPlanet which does
+it differently from IIS. Check your web server documentation for
+the details for your particular server.
=head2 How do I edit my .htpasswd and .htgroup files with Perl?
RFC-822 (the mail header standard) compliant, and addresses that aren't
deliverable which are compliant.
+You can use the Email::Valid or RFC::RFC822::Address which check
+the format of the address, although they cannot actually tell you
+if it is a deliverable address (i.e. that mail to the address
+will not bounce). Modules like Mail::CheckUser and Mail::EXPN
+try to interact with the domain name system or particular
+mail servers to learn even more, but their methods do not
+work everywhere---especially for security conscious administrators.
+
Many are tempted to try to eliminate many frequently-invalid
mail addresses with a simple regex, such as
C</^[\w.-]+\@(?:[\w-]+\.)+\w+$/>. It's a very bad idea. However,