diff options
author | Perl 5 Porters <perl5-porters@africa.nicoh.com> | 1997-03-09 11:57:19 +1200 |
---|---|---|
committer | Chip Salzenberg <chip@atlantic.net> | 1997-03-09 11:57:19 +1200 |
commit | 68dc074516a6859e3424b48d1647bcb08b1a1a7d (patch) | |
tree | 125011c6d8e4a04727ff97166dc19199809958e4 /pod/perlfaq5.pod | |
parent | 699e6cd4da8c333ef83554732e73ab6734463b5d (diff) | |
download | perl-68dc074516a6859e3424b48d1647bcb08b1a1a7d.tar.gz |
[inseparable changes from match from perl-5.003_93 to perl-5.003_94]
BUILD PROCESS
Subject: Don't use db 2.x, we're not yet ready for it
From: Paul Marquess <pmarquess@bfsec.bt.co.uk>
Files: Configure
Subject: Warn if #! command is longer than 32 chars
From: Chip Salzenberg <chip@perl.com>
Files: Configure
Subject: patches re perl -wc install{perl,man}
Date: Tue, 11 Mar 97 13:13:16 GMT
From: Robin Barker <rmb1@cise.npl.co.uk>
Files: installman installperl
I got the new installhtml from CPAN
(TOMC/scripts/pod2html-v2.0beta.shar.gz)
I had problems getting the system call to splitpod at line 376 to work.
1. splitroot was not being found
2. splitroot was not finding its library
3. I changed htmlroot to podroot at line 175 to match the documentation.
p5p-msgid: 3180.9703270906@tempest.cise.npl.co.uk
private-msgid: 21544.9703111313@tempest.cise.npl.co.uk
Subject: 3_93 doesn't install pods
Date: Sun, 16 Mar 1997 02:21:35 -0500
From: Spider Boardman <spider@orb.nashua.nh.us>
Files: installperl
Msg-ID: 199703160721.CAA08339@Orb.Nashua.NH.US
(applied based on p5p patch as commit 43506a616735d616e03d277d64fbae1e864024bf)
Subject: When installing, use File::Copy instead of `cp`
From: Chip Salzenberg <chip@perl.com>
Files: installperl
Subject: Make hint files' warnings more visible
Date: Thu, 20 Mar 1997 23:18:03 +0100 (MET)
From: Hallvard B Furuseth <h.b.furuseth@usit.uio.no>
Files: hints/3b1.sh hints/apollo.sh hints/cxux.sh hints/dcosx.sh hints/dgux.sh hints/esix4.sh hints/freebsd.sh hints/hpux.sh hints/irix_4.sh hints/mips.sh hints/next_3_0.sh hints/os2.sh hints/qnx.sh hints/sco_2_3_3.sh hints/sco_2_3_4.sh hints/solaris_2.sh hints/ultrix_4.sh hints/utekv.sh
private-msgid: 199703202218.XAA09041@bombur2.uio.no
CORE LANGUAGE CHANGES
Subject: Defer creation of array and hash elements as parameters
From: Chip Salzenberg <chip@perl.com>
Files: dump.c global.sym mg.c op.c op.h perl.h pp.c pp_hot.c proto.h sv.c
Subject: New special literal: __PACKAGE__
From: Chip Salzenberg <chip@perl.com>
Files: keywords.pl pod/perldata.pod toke.c
Subject: Abort compilation at C<BEGIN{}> or C<use> after errors
From: Chip Salzenberg <chip@perl.com>
Files: op.c pod/perldiag.pod t/pragma/subs.t
Subject: allow C<substr 'hello', -10>
Date: Mon, 10 Mar 1997 15:55:44 -0800
From: David Dyck <dcd@tc.fluke.com>
Files: pp.c
Msg-ID: 97Mar10.155517pst.35716-2@gateway.fluke.com
(applied based on p5p patch as commit 77f720bf92f3d0100352416caeedd57936807ff2)
Subject: Regularize C<x % y>, esp. when y is negative
From: Chip Salzenberg <chip@perl.com>
Files: pp.c
Subject: Flush before C<flock(FOO, LOCK_UN)>
From: Chip Salzenberg <chip@perl.com>
Files: pod/perldelta.pod pod/perlfunc.pod pp_sys.c
Subject: Close loopholes in prototype mismatch warning
From: Chip Salzenberg <chip@perl.com>
Files: op.c sv.c toke.c
Subject: Warn on C<while ($x = each %y) {}>
From: Chip Salzenberg <chip@perl.com>
Files: op.c pod/perldiag.pod
Subject: Don't warn on C<print $fh func()>
From: Chip Salzenberg <chip@perl.com>
Files: toke.c
CORE PORTABILITY
Subject: Don't say 'static var = 1'
Date: Sun, 9 Mar 1997 15:19:57 +0200 (EET)
From: Jarkko Hietaniemi <jhi@iki.fi>
Files: malloc.c
private-msgid: 199703091319.PAA24714@alpha.hut.fi
Subject: HP/UX hint comments
Date: Fri, 21 Mar 1997 15:43:07 -0500 (EST)
From: Andy Dougherty <doughera@fractal.phys.lafayette.edu>
Files: hints/hpux.sh
private-msgid: Pine.SOL.3.95q.970321153918.28770B-100000@fractal.lafayette.
Subject: VMS update
Date: Tue, 11 Mar 1997 22:00:55 -0500 (EST)
From: Charles Bailey <bailey@hmivax.humgen.upenn.edu>
Files: lib/ExtUtils/MM_VMS.pm lib/Test/Harness.pm t/op/taint.t utils/perlbug.PL vms/descrip.mms
Msg-ID: 1997Mar11.220056.1873182@hmivax.humgen.upenn.edu
(applied based on p5p patch as commit 2b5725676da60b49978f38b85bb7f8ee20b4cb55)
Subject: vmsish.t and related patches
Date: Fri, 21 Mar 1997 01:32:47 -0500 (EST)
From: Charles Bailey <bailey@HMIVAX.HUMGEN.UPENN.EDU>
Files: MANIFEST perl.h vms/descrip.mms vms/ext/vmsish.t vms/vms.c
private-msgid: 01IGQW3IP1KK005VFB@hmivax.humgen.upenn.edu
Subject: Win32 update (four patches)
From: Gurusamy Sarathy <gsar@engin.umich.edu>
Files: MANIFEST README.win32 lib/AutoSplit.pm lib/Cwd.pm lib/ExtUtils/Command.pm lib/ExtUtils/Install.pm lib/ExtUtils/MM_OS2.pm lib/ExtUtils/MM_Unix.pm lib/ExtUtils/MM_Win32.pm lib/ExtUtils/MakeMaker.pm lib/ExtUtils/Mksymlists.pm lib/File/Basename.pm lib/File/Path.pm mg.c t/comp/cpp.t t/comp/script.t t/harness t/io/argv.t t/io/dup.t t/io/fs.t t/io/inplace.t t/lib/filehand.t t/lib/io_dup.t t/lib/io_sel.t t/lib/io_taint.t t/op/closure.t t/op/exec.t t/op/glob.t t/op/goto.t t/op/magic.t t/op/misc.t t/op/rand.t t/op/split.t t/op/stat.t t/op/sysio.t t/op/taint.t t/pragma/strict.t t/pragma/subs.t t/pragma/warning.t util.c win32/*
DOCUMENTATION
Subject: perlfaq.pod
Date: Mon, 17 Mar 1997 16:01:40 -0700
From: Tom Christiansen <tchrist@jhereg.perl.com>
Files: MANIFEST pod/Makefile pod/buildtoc pod/perl.pod pod/perlfaq*.pod pod/roffitall
private-msgid: 199703172301.QAA12566@jhereg.perl.com
Subject: *.pod changes based on the FAQ
Date: Mon, 17 Mar 1997 09:50:14 -0700 (MST)
From: Nat Torkington <gnat@frii.com>
Files: pod/perldata.pod pod/perlfunc.pod pod/perlipc.pod pod/perlop.pod pod/perlre.pod pod/perlrun.pod pod/perlsec.pod pod/perlvar.pod
Msg-ID: 199703171650.JAA02655@elara.frii.com
(applied based on p5p patch as commit 3c10ad8e31f7d77e71c048b1746912f41cb540f0)
Subject: Document that $. is not reset on implicit open
From: Chip Salzenberg <chip@perl.com>
Files: pod/perldelta.pod
Subject: Re: Embedding success with _93
Date: Tue, 11 Mar 1997 17:55:05 -0500
From: Doug MacEachern <dougm@opengroup.org>
Files: pod/perldelta.pod
Msg-ID: 199703112255.RAA22775@postman.osf.org
(applied based on p5p patch as commit 63a6ff3a1dc8d86edb4d8a7ec1548205e32a7114)
Subject: Patch to document illegal characters
Date: Fri, 14 Mar 1997 09:08:10 -0800 (PST)
From: Tom Phoenix <rootbeer@teleport.com>
Files: pod/perldiag.pod pod/perltrap.pod
private-msgid: Pine.GSO.3.96.970314090558.15346J-100000@kelly.teleport.com
Subject: Document trap with //o and closures
Date: Mon, 10 Mar 1997 18:08:08 -0500 (EST)
From: Charles Bailey <bailey@HMIVAX.HUMGEN.UPENN.EDU>
Files: pod/perltrap.pod
Msg-ID: 01IGCHWRNSEU00661G@hmivax.humgen.upenn.edu
(applied based on p5p patch as commit a54cb1465fdb400848f23705a6f130bb5c34ab70)
Subject: Illegal character in input
Date: Mon, 10 Mar 1997 15:21:21 -0800 (PST)
From: Tom Phoenix <rootbeer@teleport.com>
Files: pod/perldiag.pod
private-msgid: Pine.GSO.3.95q.970310151512.22489a-100000@kelly.teleport.com
Subject: Patch for docs Re: Lost backslash
Date: Wed, 19 Mar 1997 07:28:57 -0800 (PST)
From: Tom Phoenix <rootbeer@teleport.com>
Files: pod/perlop.pod
private-msgid: Pine.GSO.3.96.970319071438.24834G-100000@kelly.teleport.com
Subject: XSUB's doc fix
Date: Mon, 10 Mar 1997 11:42:06 -0500
From: Roderick Schertler <roderick@argon.org>
Files: pod/perlcall.pod pod/perlguts.pod pod/perlxstut.pod
Msg-ID: 28804.858012126@eeyore.ibcinc.com
(applied based on p5p patch as commit 5f43237038ea7a4151d3bf65aeeecd56ceb78a6a)
Subject: Document return from do FILE
Date: Tue, 18 Mar 1997 14:50:10 +0000
From: "M.J.T. Guy" <mjtg@cus.cam.ac.uk>
Files: pod/perlfunc.pod
Msg-ID: E0w70DK-0001yJ-00@ursa.cus.cam.ac.uk
(applied based on p5p patch as commit ba8d5fb439878113de8abc9b52d2af237d30fb3c)
Subject: Document $^M in perlvar
Date: Thu, 20 Mar 97 21:08:33 GMT
From: Robin Barker <rmb1@cise.npl.co.uk>
Files: pod/perlvar.pod
private-msgid: 6153.9703202108@tempest.cise.npl.co.uk
Subject: typos in pods of 5.003_93
Date: 19 Mar 1997 10:39:38 -0600
From: Jim Meyering <meyering@asic.sc.ti.com>
Files: pod/perlfunc.pod pod/perlguts.pod pod/perlre.pod pod/perltoot.pod pod/perlxs.pod
Msg-ID: wpgendbzvhx.fsf@asic.sc.ti.com
(applied based on p5p patch as commit 76a9873e006cf8f48f57062b2a0dd40b5ed45a95)
Subject: Re: Updates to pod punctuations
Date: Fri, 14 Mar 1997 17:00:12 -0500
From: Larry W. Virden <lvirden@cas.org>
Files: pod/*.pod
private-msgid: 9703141700.AA22911@cas.org
Subject: clarify example in perlfunc
Date: Thu, 20 Mar 1997 19:46:01 +0200 (EET)
From: Jarkko Hietaniemi <jhi@iki.fi>
Files: pod/perlfunc.pod
private-msgid: 199703201746.TAA25195@alpha.hut.fi
Subject: Regularize headings in DB_File documentation
From: Chip Salzenberg <chip@perl.com>
Files: ext/DB_File/DB_File.pm
LIBRARY AND EXTENSIONS
Subject: New module: autouse.pm
Date: Thu, 20 Mar 1997 19:34:30 -0500 (EST)
From: Ilya Zakharevich <ilya@math.ohio-state.edu>
Files: MANIFEST lib/autouse.pm
Msg-ID: 199703210034.TAA13469@monk.mps.ohio-state.edu
(applied based on p5p patch as commit 6757905eccb6dd0440ef65e8128a277a20f7d943)
Subject: Refresh DB_File to 1.12
Date: Wed, 12 Mar 97 15:51:14 GMT
From: Paul Marquess <pmarquess@bfsec.bt.co.uk>
Files: ext/DB_File/DB_File.pm ext/DB_File/DB_File.xs
Msg-ID: 9703121551.AA07435@claudius.bfsec.bt.co.uk
(applied based on p5p patch as commit b3deed9189f963e9994815307931f9084f60d1d9)
Subject: In File::Path, some systems can't remove read-only files
From: Chip Salzenberg <chip@perl.com>
Files: lib/File/Path.pm
Subject: Fix bugs revealed by prototype warnings
From: Chip Salzenberg <chip@perl.com>
Files: ext/Opcode/Opcode.pm lib/ExtUtils/MakeMaker.pm lib/Getopt/Long.pm
Subject: Problems with SKIP in makemaker
Date: Thu, 20 Mar 1997 23:13:31 -0500 (EST)
From: Ilya Zakharevich <ilya@math.ohio-state.edu>
Files: lib/ExtUtils/MM_Unix.pm
Msg-ID: 199703210413.XAA21601@monk.mps.ohio-state.edu
(applied based on p5p patch as commit 970322a2e8024294ada6e8d1a027cb98f1f48ee3)
Subject: In Exporter, don't C<require Carp> at file scope
From: Chip Salzenberg <chip@perl.com>
Files: lib/Exporter.pm
Subject: fix for Exporter's $SIG{__WARN__} handler
Date: Thu, 13 Mar 1997 18:40:51 -0500
From: Roderick Schertler <roderick@argon.org>
Files: lib/Exporter.pm
Msg-ID: 2282.858296451@eeyore.ibcinc.com
(applied based on p5p patch as commit 2768ea1aeef34f42d096f198fbe629c8374ca429)
Subject: Don't try to substr() refs in Carp
From: Chip Salzenberg <chip@perl.com>
Files: lib/Carp.pm
Subject: Re: NUL in die and other messages
Date: Fri, 21 Mar 1997 09:58:17 +0000
From: "M.J.T. Guy" <mjtg@cus.cam.ac.uk>
Files: lib/Carp.pm
Msg-ID: E0w815V-0005xs-00@ursa.cus.cam.ac.uk
(applied based on p5p patch as commit 52a267c574cb66c4bc35601dcf148a1d7a3bc557)
OTHER CORE CHANGES
Subject: Guard against buffer overflow in yyerror() and related funcs
From: Chip Salzenberg <chip@perl.com>
Files: toke.c
Subject: For bin compat, rename calllist() and he_{,delay}free
From: Chip Salzenberg <chip@perl.com>
Files: global.sym hv.c op.c perl.c pod/perlguts.pod proto.h
Subject: Fix C<print> on tied default handle
From: Chip Salzenberg <chip@perl.com>
Files: pp_hot.c
Subject: Fix C<local($a, undef, $b) = (1,2,3)>
From: Chip Salzenberg <chip@perl.com>
Files: op.c
Subject: Improve diagnostic on C<@a++>, C<--%a>, @a =~ s/a/b/
From: Chip Salzenberg <chip@perl.com>
Files: pp.c pp_hot.c
Subject: Don't warn on C<$x{y} .= "z"> when %x is tied
From: Chip Salzenberg <chip@perl.com>
Files: pp_hot.c
Subject: Eliminate 'unreachable code' warnings
From: Chip Salzenberg <chip@perl.com>
Files: ext/POSIX/POSIX.xs mg.c pp_ctl.c toke.c
Subject: printf format corrections for -DDEBUGGING
Date: Wed, 19 Mar 1997 12:42:50 -0500
From: Roderick Schertler <roderick@argon.org>
Files: doop.c malloc.c op.c pp_ctl.c regexec.c sv.c x2p/str.c x2p/util.c
Msg-ID: 26592.858793370@eeyore.ibcinc.com
(applied based on p5p patch as commit e125f273e351a19a92b69d6244af55abbbf0a26d)
Subject: Warn about missing -DMULTIPLICITY if likely a problem
Date: Wed, 19 Mar 1997 18:45:53 -0500
From: Doug MacEachern <dougm@opengroup.org>
Files: perl.c
Msg-ID: 199703192345.SAA15070@postman.osf.org
(applied based on p5p patch as commit 71aeea1753924e6e19c2461e241e3f7d8a570e90)
Diffstat (limited to 'pod/perlfaq5.pod')
-rw-r--r-- | pod/perlfaq5.pod | 788 |
1 files changed, 788 insertions, 0 deletions
diff --git a/pod/perlfaq5.pod b/pod/perlfaq5.pod new file mode 100644 index 0000000000..c36576ff7f --- /dev/null +++ b/pod/perlfaq5.pod @@ -0,0 +1,788 @@ +=head1 NAME + +perlfaq5 - Files and Formats ($Revision: 1.19 $) + +=head1 DESCRIPTION + +This section deals with I/O and the "f" issues: filehandles, flushing, +formats, and footers. + +=head2 How do I flush/unbuffer a filehandle? Why must I do this? + +The C standard I/O library (stdio) normally buffers characters sent to +devices. This is done for efficiency reasons, so that there isn't a +system call for each byte. Any time you use print() or write() in +Perl, you go though this buffering. syswrite() circumvents stdio and +buffering. + +In most stdio implementations, the type of buffering and the size of +the buffer varies according to the type of device. Disk files are block +buffered, often with a buffer size of more than 2k. Pipes and sockets +are often buffered with a buffer size between 1/2 and 2k. Serial devices +(e.g. modems, terminals) are normally line-buffered, and stdio sends +the entire line when it gets the newline. + +Perl does not support truly unbuffered output (except insofar as you can +C<syswrite(OUT, $char, 1)>). What it does instead support is "command +buffering", in which a physical write is performed after every output +command. This isn't as hard on your system as unbuffering, but does +get the output where you want it when you want it. + +If you expect characters to get to your device when you print them there, +you'll want to autoflush its handle, as in the older: + + use FileHandle; + open(DEV, "<+/dev/tty"); # ceci n'est pas une pipe + DEV->autoflush(1); + +or the newer IO::* modules: + + use IO::Handle; + open(DEV, ">/dev/printer"); # but is this? + DEV->autoflush(1); + +or even this: + + use IO::Socket; # this one is kinda a pipe? + $sock = IO::Socket::INET->new(PeerAddr => 'www.perl.com', + PeerPort => 'http(80)', + Proto => 'tcp'); + die "$!" unless $sock; + + $sock->autoflush(); + $sock->print("GET /\015\012"); + $document = join('', $sock->getlines()); + print "DOC IS: $document\n"; + +Note the hardcoded carriage return and newline in their octal +equivalents. This is the ONLY way (currently) to assure a proper +flush on all platforms, including Macintosh. + +You can use select() and the C<$|> variable to control autoflushing +(see L<perlvar/$|> and L<perlfunc/select>): + + $oldh = select(DEV); + $| = 1; + select($oldh); + +You'll also see code that does this without a temporary variable, as in + + select((select(DEV), $| = 1)[0]); + +=head2 How do I change one line in a file/delete a line in a file/insert a line in the middle of a file/append to the beginning of a file? + +Although humans have an easy time thinking of a text file as being a +sequence of lines that operates much like a stack of playing cards -- +or punch cards -- computers usually see the text file as a sequence of +bytes. In general, there's no direct way for Perl to seek to a +particular line of a file, insert text into a file, or remove text +from a file. + +(There are exceptions in special circumstances. Replacing a sequence +of bytes with another sequence of the same length is one. Another is +using the C<$DB_RECNO> array bindings as documented in L<DB_File>. +Yet another is manipulating files with all lines the same length.) + +The general solution is to create a temporary copy of the text file with +the changes you want, then copy that over the original. + + $old = $file; + $new = "$file.tmp.$$"; + $bak = "$file.bak"; + + open(OLD, "< $old") or die "can't open $old: $!"; + open(NEW, "> $new") or die "can't open $new: $!"; + + # Correct typos, preserving case + while (<OLD>) { + s/\b(p)earl\b/${1}erl/i; + (print NEW $_) or die "can't write to $new: $!"; + } + + close(OLD) or die "can't close $old: $!"; + close(NEW) or die "can't close $new: $!"; + + rename($old, $bak) or die "can't rename $old to $bak: $!"; + rename($new, $old) or die "can't rename $new to $old: $!"; + +Perl can do this sort of thing for you automatically with the C<-i> +command-line switch or the closely-related C<$^I> variable (see +L<perlrun> for more details). Note that +C<-i> may require a suffix on some non-Unix systems; see the +platform-specific documentation that came with your port. + + # Renumber a series of tests from the command line + perl -pi -e 's/(^\s+test\s+)\d+/ $1 . ++$count /e' t/op/taint.t + + # form a script + local($^I, @ARGV) = ('.bak', glob("*.c")); + while (<>) { + if ($. == 1) { + print "This line should appear at the top of each file\n"; + } + s/\b(p)earl\b/${1}erl/i; # Correct typos, preserving case + print; + close ARGV if eof; # Reset $. + } + +If you need to seek to an arbitrary line of a file that changes +infrequently, you could build up an index of byte positions of where +the line ends are in the file. If the file is large, an index of +every tenth or hundredth line end would allow you to seek and read +fairly efficiently. If the file is sorted, try the look.pl library +(part of the standard perl distribution). + +In the unique case of deleting lines at the end of a file, you +can use tell() and truncate(). The following code snippet deletes +the last line of a file without making a copy or reading the +whole file into memory: + + open (FH, "+< $file"); + while ( <FH> ) { $addr = tell(FH) unless eof(FH) } + truncate(FH, $addr); + +Error checking is left as an exercise for the reader. + +=head2 How do I count the number of lines in a file? + +One fairly efficient way is to count newlines in the file. The +following program uses a feature of tr///, as documented in L<perlop>. +If your text file doesn't end with a newline, then it's not really a +proper text file, so this may report one fewer line than you expect. + + $lines = 0; + open(FILE, $filename) or die "Can't open `$filename': $!"; + while (sysread FILE, $buffer, 4096) { + $lines += ($buffer =~ tr/\n//); + } + close FILE; + +=head2 How do I make a temporary file name? + +Use the process ID and/or the current time-value. If you need to have +many temporary files in one process, use a counter: + + BEGIN { + use IO::File; + use Fcntl; + my $temp_dir = -d '/tmp' ? '/tmp' : $ENV{TMP} || $ENV{TEMP}; + my $base_name = sprintf("%s/%d-%d-0000", $temp_dir, $$, time()); + sub temp_file { + my $fh = undef; + my $count = 0; + until (defined($fh) || $count > 100) { + $base_name =~ s/-(\d+)$/"-" . (1 + $1)/e; + $fh = IO::File->new($base_name, O_WRONLY|O_EXCL|O_CREAT, 0644) + } + if (defined($fh)) { + return ($fh, $base_name); + } else { + return (); + } + } + } + +Or you could simply use IO::Handle::new_tmpfile. + +=head2 How can I manipulate fixed-record-length files? + +The most efficient way is using pack() and unpack(). This is faster +than using substr(). Here is a sample chunk of code to break up and +put back together again some fixed-format input lines, in this case +from the output of a normal, Berkeley-style ps: + + # sample input line: + # 15158 p5 T 0:00 perl /home/tchrist/scripts/now-what + $PS_T = 'A6 A4 A7 A5 A*'; + open(PS, "ps|"); + $_ = <PS>; print; + while (<PS>) { + ($pid, $tt, $stat, $time, $command) = unpack($PS_T, $_); + for $var (qw!pid tt stat time command!) { + print "$var: <$$var>\n"; + } + print 'line=', pack($PS_T, $pid, $tt, $stat, $time, $command), + "\n"; + } + +=head2 How can I make a filehandle local to a subroutine? How do I pass filehandles between subroutines? How do I make an array of filehandles? + +You may have some success with typeglobs, as we always had to use +in days of old: + + local(*FH); + +But while still supported, that isn't the best to go about getting +local filehandles. Typeglobs have their drawbacks. You may well want +to use the C<FileHandle> module, which creates new filehandles for you +(see L<FileHandle>): + + use FileHandle; + sub findme { + my $fh = FileHandle->new(); + open($fh, "</etc/hosts") or die "no /etc/hosts: $!"; + while (<$fh>) { + print if /\b127\.(0\.0\.)?1\b/; + } + # $fh automatically closes/disappears here + } + +Internally, Perl believes filehandles to be of class IO::Handle. You +may use that module directly if you'd like (see L<IO::Handle>), or +one of its more specific derived classes. + +=head2 How can I set up a footer format to be used with write()? + +There's no built-in way to do this, but L<perlform> has a couple of +techniques to make it possible for the intrepid hacker. + +=head2 How can I write() into a string? + +See L<perlform> for an swrite() function. + +=head2 How can I output my numbers with commas added? + +This one will do it for you: + + sub commify { + local $_ = shift; + 1 while s/^(-?\d+)(\d{3})/$1,$2/; + return $_; + } + + $n = 23659019423.2331; + print "GOT: ", commify($n), "\n"; + + GOT: 23,659,019,423.2331 + +You can't just: + + s/^(-?\d+)(\d{3})/$1,$2/g; + +because you have to put the comma in and then recalculate your +position. + +=head2 How can I translate tildes (~) in a filename? + +Use the E<lt>E<gt> (glob()) operator, documented in L<perlfunc>. This +requires that you have a shell installed that groks tildes, meaning +csh or tcsh or (some versions of) ksh, and thus may have portability +problems. The Glob::KGlob module (available from CPAN) gives more +portable glob functionality. + +Within Perl, you may use this directly: + + $filename =~ s{ + ^ ~ # find a leading tilde + ( # save this in $1 + [^/] # a non-slash character + * # repeated 0 or more times (0 means me) + ) + }{ + $1 + ? (getpwnam($1))[7] + : ( $ENV{HOME} || $ENV{LOGDIR} ) + }ex; + +=head2 How come when I open the file read-write it wipes it out? + +Because you're using something like this, which truncates the file and +I<then> gives you read-write access: + + open(FH, "+> /path/name"); # WRONG + +Whoops. You should instead use this, which will fail if the file +doesn't exist. + + open(FH, "+< /path/name"); # open for update + +If this is an issue, try: + + sysopen(FH, "/path/name", O_RDWR|O_CREAT, 0644); + +Error checking is left as an exercise for the reader. + +=head2 Why do I sometimes get an "Argument list too long" when I use <*>? + +The C<E<lt>E<gt>> operator performs a globbing operation (see above). +By default glob() forks csh(1) to do the actual glob expansion, but +csh can't handle more than 127 items and so gives the error message +C<Argument list too long>. People who installed tcsh as csh won't +have this problem, but their users may be surprised by it. + +To get around this, either do the glob yourself with C<Dirhandle>s and +patterns, or use a module like Glob::KGlob, one that doesn't use the +shell to do globbing. + +=head2 Is there a leak/bug in glob()? + +Due to the current implementation on some operating systems, when you +use the glob() function or its angle-bracket alias in a scalar +context, you may cause a leak and/or unpredictable behavior. It's +best therefore to use glob() only in list context. + +=head2 How can I open a file with a leading "E<gt>" or trailing blanks? + +Normally perl ignores trailing blanks in filenames, and interprets +certain leading characters (or a trailing "|") to mean something +special. To avoid this, you might want to use a routine like this. +It makes incomplete pathnames into explicit relative ones, and tacks a +trailing null byte on the name to make perl leave it alone: + + sub safe_filename { + local $_ = shift; + return m#^/# + ? "$_\0" + : "./$_\0"; + } + + $fn = safe_filename("<<<something really wicked "); + open(FH, "> $fn") or "couldn't open $fn: $!"; + +You could also use the sysopen() function (see L<perlfunc/sysopen>). + +=head2 How can I reliably rename a file? + +Well, usually you just use Perl's rename() function. But that may +not work everywhere, in particular, renaming files across file systems. +If your operating system supports a mv(1) program or its moral equivalent, +this works: + + rename($old, $new) or system("mv", $old, $new); + +It may be more compelling to use the File::Copy module instead. You +just copy to the new file to the new name (checking return values), +then delete the old one. This isn't really the same semantics as a +real rename(), though, which preserves metainformation like +permissions, timestamps, inode info, etc. + +=head2 How can I lock a file? + +Perl's built-in flock() function (see L<perlfunc> for details) will call +flock(2) if that exists, fcntl(2) if it doesn't (on perl version 5.004 and +later), and lockf(3) if neither of the two previous system calls exists. +On some systems, it may even use a different form of native locking. +Here are some gotchas with Perl's flock(): + +=over 4 + +=item 1 + +Produces a fatal error if none of the three system calls (or their +close equivalent) exists. + +=item 2 + +lockf(3) does not provide shared locking, and requires that the +filehandle be open for writing (or appending, or read/writing). + +=item 3 + +Some versions of flock() can't lock files over a network (e.g. on NFS +file systems), so you'd need to force the use of fcntl(2) when you +build Perl. See the flock entry of L<perlfunc>, and the F<INSTALL> +file in the source distribution for information on building Perl to do +this. + +=back + +The CPAN module File::Lock offers similar functionality and (if you +have dynamic loading) won't require you to rebuild perl if your +flock() can't lock network files. + +=head2 What can't I just open(FH, ">file.lock")? + +A common bit of code B<NOT TO USE> is this: + + sleep(3) while -e "file.lock"; # PLEASE DO NOT USE + open(LCK, "> file.lock"); # THIS BROKEN CODE + +This is a classic race condition: you take two steps to do something +which must be done in one. That's why computer hardware provides an +atomic test-and-set instruction. In theory, this "ought" to work: + + sysopen(FH, "file.lock", O_WRONLY|O_EXCL|O_CREAT, 0644) + or die "can't open file.lock: $!": + +except that lamentably, file creation (and deletion) is not atomic +over NFS, so this won't work (at least, not every time) over the net. +Various schemes involving involving link() have been suggested, but +these tend to involve busy-wait, which is also subdesirable. + +=head2 I still don't get locking. I just want to increment the number +in the file. How can I do this? + +Didn't anyone ever tell you web-page hit counters were useless? + +Anyway, this is what to do: + + use Fcntl; + sysopen(FH, "numfile", O_RDWR|O_CREAT, 0644) or die "can't open numfile: $!"; + flock(FH, 2) or die "can't flock numfile: $!"; + $num = <FH> || 0; + seek(FH, 0, 0) or die "can't rewind numfile: $!"; + truncate(FH, 0) or die "can't truncate numfile: $!"; + (print FH $num+1, "\n") or die "can't write numfile: $!"; + # DO NOT UNLOCK THIS UNTIL YOU CLOSE + close FH or die "can't close numfile: $!"; + +Here's a much better web-page hit counter: + + $hits = int( (time() - 850_000_000) / rand(1_000) ); + +If the count doesn't impress your friends, then the code might. :-) + +=head2 How do I randomly update a binary file? + +If you're just trying to patch a binary, in many cases something as +simple as this works: + + perl -i -pe 's{window manager}{window mangler}g' /usr/bin/emacs + +However, if you have fixed sized records, then you might do something more +like this: + + $RECSIZE = 220; # size of record, in bytes + $recno = 37; # which record to update + open(FH, "+<somewhere") || die "can't update somewhere: $!"; + seek(FH, $recno * $RECSIZE, 0); + read(FH, $record, $RECSIZE) == $RECSIZE || die "can't read record $recno: $!"; + # munge the record + seek(FH, $recno * $RECSIZE, 0); + print FH $record; + close FH; + +Locking and error checking are left as an exercise for the reader. +Don't forget them, or you'll be quite sorry. + +Don't forget to set binmode() under DOS-like platforms when operating +on files that have anything other than straight text in them. See the +docs on open() and on binmode() for more details. + +=head2 How do I get a file's timestamp in perl? + +If you want to retrieve the time at which the file was last read, +written, or had its meta-data (owner, etc) changed, you use the B<-M>, +B<-A>, or B<-C> filetest operations as documented in L<perlfunc>. These +retrieve the age of the file (measured against the start-time of your +program) in days as a floating point number. To retrieve the "raw" +time in seconds since the epoch, you would call the stat function, +then use localtime(), gmtime(), or POSIX::strftime() to convert this +into human-readable form. + +Here's an example: + + $write_secs = (stat($file))[9]; + print "file $file updated at ", scalar(localtime($file)), "\n"; + +If you prefer something more legible, use the File::stat module +(part of the standard distribution in version 5.004 and later): + + use File::stat; + use Time::localtime; + $date_string = ctime(stat($file)->mtime); + print "file $file updated at $date_string\n"; + +Error checking is left as an exercise for the reader. + +=head2 How do I set a file's timestamp in perl? + +You use the utime() function documented in L<perlfunc/utime>. +By way of example, here's a little program that copies the +read and write times from its first argument to all the rest +of them. + + if (@ARGV < 2) { + die "usage: cptimes timestamp_file other_files ...\n"; + } + $timestamp = shift; + ($atime, $mtime) = (stat($timestamp))[8,9]; + utime $atime, $mtime, @ARGV; + +Error checking is left as an exercise for the reader. + +Note that utime() currently doesn't work correctly with Win95/NT +ports. A bug has been reported. Check it carefully before using +it on those platforms. + +=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: + + open (FH, "| tee file1 file2 file3"); + +Otherwise you'll have to write your own multiplexing print function -- +or your own tee program -- or use Tom Christiansen's, at +http://www.perl.com/CPAN/authors/id/TOMC/scripts/tct.gz, which is +written in Perl. + +In theory a IO::Tee class could be written, but to date we haven't +seen such. + +=head2 How can I read in a file by paragraphs? + +Use the C<$\> variable (see L<perlvar> for details). You can either +set it to C<""> to eliminate empty paragraphs (C<"abc\n\n\n\ndef">, +for instance, gets treated as two paragraphs and not three), or +C<"\n\n"> to accept empty paragraphs. + +=head2 How can I read a single character from a file? From the keyboard? + +You can use the builtin C<getc()> function for most filehandles, but +it won't (easily) work on a terminal device. For STDIN, either use +the Term::ReadKey module from CPAN, or use the sample code in +L<perlfunc/getc>. + +If your system supports POSIX, you can use the following code, which +you'll note turns off echo processing as well. + + #!/usr/bin/perl -w + use strict; + $| = 1; + for (1..4) { + my $got; + print "gimme: "; + $got = getone(); + print "--> $got\n"; + } + exit; + + BEGIN { + use POSIX qw(:termios_h); + + my ($term, $oterm, $echo, $noecho, $fd_stdin); + + $fd_stdin = fileno(STDIN); + + $term = POSIX::Termios->new(); + $term->getattr($fd_stdin); + $oterm = $term->getlflag(); + + $echo = ECHO | ECHOK | ICANON; + $noecho = $oterm & ~$echo; + + sub cbreak { + $term->setlflag($noecho); + $term->setcc(VTIME, 1); + $term->setattr($fd_stdin, TCSANOW); + } + + sub cooked { + $term->setlflag($oterm); + $term->setcc(VTIME, 0); + $term->setattr($fd_stdin, TCSANOW); + } + + sub getone { + my $key = ''; + cbreak(); + sysread(STDIN, $key, 1); + cooked(); + return $key; + } + + } + + END { cooked() } + +The Term::ReadKey module from CPAN may be easier to use: + + use Term::ReadKey; + open(TTY, "</dev/tty"); + print "Gimme a char: "; + ReadMode "raw"; + $key = ReadKey 0, *TTY; + ReadMode "normal"; + printf "\nYou said %s, char number %03d\n", + $key, ord $key; + +For DOS systems, Dan Carson <dbc@tc.fluke.COM> reports the following: + +To put the PC in "raw" mode, use ioctl with some magic numbers gleaned +from msdos.c (Perl source file) and Ralf Brown's interrupt list (comes +across the net every so often): + + $old_ioctl = ioctl(STDIN,0,0); # Gets device info + $old_ioctl &= 0xff; + ioctl(STDIN,1,$old_ioctl | 32); # Writes it back, setting bit 5 + +Then to read a single character: + + sysread(STDIN,$c,1); # Read a single character + +And to put the PC back to "cooked" mode: + + ioctl(STDIN,1,$old_ioctl); # Sets it back to cooked mode. + +So now you have $c. If C<ord($c) == 0>, you have a two byte code, which +means you hit a special key. Read another byte with C<sysread(STDIN,$c,1)>, +and that value tells you what combination it was according to this +table: + + # PC 2-byte keycodes = ^@ + the following: + + # HEX KEYS + # --- ---- + # 0F SHF TAB + # 10-19 ALT QWERTYUIOP + # 1E-26 ALT ASDFGHJKL + # 2C-32 ALT ZXCVBNM + # 3B-44 F1-F10 + # 47-49 HOME,UP,PgUp + # 4B LEFT + # 4D RIGHT + # 4F-53 END,DOWN,PgDn,Ins,Del + # 54-5D SHF F1-F10 + # 5E-67 CTR F1-F10 + # 68-71 ALT F1-F10 + # 73-77 CTR LEFT,RIGHT,END,PgDn,HOME + # 78-83 ALT 1234567890-= + # 84 CTR PgUp + +This is all trial and error I did a long time ago, I hope I'm reading the +file that worked. + +=head2 How can I tell if there's a character waiting on a filehandle? + +You should check out the Frequently Asked Questions list in +comp.unix.* for things like this: the answer is essentially the same. +It's very system dependent. Here's one solution that works on BSD +systems: + + sub key_ready { + my($rin, $nfd); + vec($rin, fileno(STDIN), 1) = 1; + return $nfd = select($rin,undef,undef,0); + } + +You should look into getting the Term::ReadKey extension from CPAN. + +=head2 How do I open a file without blocking? + +You need to use the O_NDELAY or O_NONBLOCK flag from the Fcntl module +in conjunction with sysopen(): + + use Fcntl; + sysopen(FH, "/tmp/somefile", O_WRONLY|O_NDELAY|O_CREAT, 0644) + or die "can't open /tmp/somefile: $!": + +=head2 How do I create a file only if it doesn't exist? + +You need to use the O_CREAT and O_EXCL flags from the Fcntl module in +conjunction with sysopen(): + + use Fcntl; + sysopen(FH, "/tmp/somefile", O_WRONLY|O_EXCL|O_CREAT, 0644) + or die "can't open /tmp/somefile: $!": + +Be warned that neither creation nor deletion of files is guaranteed to +be an atomic operation over NFS. That is, two processes might both +successful create or unlink the same file! + +=head2 How do I do a C<tail -f> in perl? + +First try + + seek(GWFILE, 0, 1); + +The statement C<seek(GWFILE, 0, 1)> doesn't change the current position, +but it does clear the end-of-file condition on the handle, so that the +next <GWFILE> makes Perl try again to read something. + +If that doesn't work (it relies on features of your stdio implementation), +then you need something more like this: + + for (;;) { + for ($curpos = tell(GWFILE); <GWFILE>; $curpos = tell(GWFILE)) { + # search for some stuff and put it into files + } + # sleep for a while + seek(GWFILE, $curpos, 0); # seek to where we had been + } + +If this still doesn't work, look into the POSIX module. POSIX defines +the clearerr() method, which can remove the end of file condition on a +filehandle. The method: read until end of file, clearerr(), read some +more. Lather, rinse, repeat. + +=head2 How do I dup() a filehandle in Perl? + +If you check L<perlfunc/open>, you'll see that several of the ways +to call open() should do the trick. For example: + + open(LOG, ">>/tmp/logfile"); + open(STDERR, ">&LOG"); + +Or even with a literal numeric descriptor: + + $fd = $ENV{MHCONTEXTFD}; + open(MHCONTEXT, "<&=$fd"); # like fdopen(3S) + +Error checking has been left as an exercise for the reader. + +=head2 How do I close a file descriptor by number? + +This should rarely be necessary, as the Perl close() function is to be +used for things that Perl opened itself, even if it was a dup of a +numeric descriptor, as with MHCONTEXT above. But if you really have +to, you may be able to do this: + + require 'sys/syscall.ph'; + $rc = syscall(&SYS_close, $fd + 0); # must force numeric + die "can't sysclose $fd: $!" unless $rc == -1; + +=head2 Why can't I use "C:\temp\foo" in DOS paths? What doesn't `C:\temp\foo.exe` work? + +Whoops! You just put a tab and a formfeed into that filename! +Remember that within double quoted strings ("like\this"), the +backslash is an escape character. The full list of these is in +L<perlop/Quote and Quote-like Operators>. Unsurprisingly, you don't +have a file called "c:(tab)emp(formfeed)oo" or +"c:(tab)emp(formfeed)oo.exe" on your DOS filesystem. + +Either single-quote your strings, or (preferably) use forward slashes. +Since all DOS and Windows versions since something like MS-DOS 2.0 or so +have treated C</> and C<\> the same in a path, you might as well use the +one that doesn't clash with Perl -- or the POSIX shell, ANSI C and C++, +awk, Tcl, Java, or Python, just to mention a few. + +=head2 Why doesn't glob("*.*") get all the files? + +Because even on non-Unix ports, Perl's glob function follows standard +Unix globbing semantics. You'll need C<glob("*")> to get all (non-hidden) +files. + +=head2 Why does Perl let me delete read-only files? Why does C<-i> clobber protected files? Isn't this a bug in Perl? + +This is elaborately and painstakingly described in the "Far More Than +You Every Wanted To Know" in +http://www.perl.com/CPAN/doc/FMTEYEWTK/file-dir-perms . + +The executive summary: learn how your filesystem works. The +permissions on a file say what can happen to the data in that file. +The permissions on a directory say what can happen to the list of +files in that directory. If you delete a file, you're removing its +name from the directory (so the operation depends on the permissions +of the directory, not of the file). If you try to write to the file, +the permissions of the file govern whether you're allowed to. + +=head2 How do I select a random line from a file? + +Here's an algorithm from the Camel Book: + + srand; + rand($.) < 1 && ($line = $_) while <>; + +This has a significant advantage in space over reading the whole +file in. + +=head1 AUTHOR AND COPYRIGHT + +Copyright (c) 1997 Tom Christiansen and Nathan Torkington. +All rights reserved. See L<perlfaq> for distribution information. |