X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pod%2Fperlfaq5.pod;h=31db204129115cf2b4b8a5da0ec9d100f0424d17;hb=af9e49b40a4cc2d6c0d5ebad7e84fb62143b24e1;hp=ca2fb7e87c3bd35da463073446ea10d06cf5aaa8;hpb=49d635f9372392ae44fe4c5b62b06e41912ae0c9;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pod/perlfaq5.pod b/pod/perlfaq5.pod index ca2fb7e..31db204 100644 --- a/pod/perlfaq5.pod +++ b/pod/perlfaq5.pod @@ -1,6 +1,6 @@ =head1 NAME -perlfaq5 - Files and Formats ($Revision: 1.26 $, $Date: 2002/09/21 21:04:17 $) +perlfaq5 - Files and Formats ($Revision: 1.38 $, $Date: 2005/10/13 19:49:13 $) =head1 DESCRIPTION @@ -8,6 +8,7 @@ This section deals with I/O and the "f" issues: filehandles, flushing, formats, and footers. =head2 How do I flush/unbuffer an output filehandle? Why must I do this? +X X X X Perl does not support truly unbuffered output (except insofar as you can C), although it @@ -30,7 +31,7 @@ value, Perl will flush the handle's buffer after each print() or write(). Setting $| affects buffering only for the currently selected default file handle. You choose this handle with the one argument select() call (see -L and L). +L> and L). Use select() to choose the desired handle, then set its per-filehandle variables. @@ -61,11 +62,13 @@ or IO::Socket: $sock->autoflush(); =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? +X Use the Tie::File module, which is included in the standard distribution since Perl 5.8.0. =head2 How do I count the number of lines in a file? +X X X One fairly efficient way is to count newlines in the file. The following program uses a feature of tr///, as documented in L. @@ -82,6 +85,7 @@ proper text file, so this may report one fewer line than you expect. This assumes no funny games with newline translations. =head2 How can I use Perl's C<-i> option from within a program? +X<-i> X C<-i> sets the value of Perl's C<$^I> variable, which in turn affects the behavior of C<< <> >>; see L for more details. By @@ -106,11 +110,35 @@ This block modifies all the C<.c> files in the current directory, leaving a backup of the original data from each file in a new C<.c.orig> file. +=head2 How can I copy a file? +X X + +(contributed by brian d foy) + +Use the File::Copy module. It comes with Perl and can do a +true copy across file systems, and it does its magic in +a portable fashion. + + use File::Copy; + + copy( $original, $new_copy ) or die "Copy failed: $!"; + +If you can't use File::Copy, you'll have to do the work yourself: +open the original file, open the destination file, then print +to the destination file as you read the original. + =head2 How do I make a temporary file name? +X + +If you don't need to know the name of the file, you can use C +with C in place of the file name. The C function +creates an anonymous temporary file. -Use the File::Temp module, see L for more information. + open my $tmp, '+>', undef or die $!; - use File::Temp qw/ tempfile tempdir /; +Otherwise, you can use the File::Temp module. + + use File::Temp qw/ tempfile tempdir /; $dir = tempdir( CLEANUP => 1 ); ($fh, $filename) = tempfile( DIR => $dir ); @@ -141,6 +169,7 @@ temporary files in one process, use a counter: my $count = 0; until (defined(fileno(FH)) || $count++ > 100) { $base_name =~ s/-(\d+)$/"-" . (1 + $1)/e; + # O_EXCL is required for security reasons. sysopen(FH, $base_name, O_WRONLY|O_EXCL|O_CREAT); } if (defined(fileno(FH)) @@ -152,9 +181,12 @@ temporary files in one process, use a counter: } =head2 How can I manipulate fixed-record-length files? +X X -The most efficient way is using pack() and unpack(). This is faster than -using substr() when taking many, many strings. It is slower for just a few. +The most efficient way is using L and +L. This is faster than using +L when taking many, many strings. It is +slower for just a few. 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, @@ -162,24 +194,26 @@ 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|"); - print scalar ; - while () { - ($pid, $tt, $stat, $time, $command) = unpack($PS_T, $_); - for $var (qw!pid tt stat time command!) { - print "$var: <$$var>\n"; + my $PS_T = 'A6 A4 A7 A5 A*'; + open my $ps, '-|', 'ps'; + print scalar <$ps>; + my @fields = qw( pid tt stat time command ); + while (<$ps>) { + my %process; + @process{@fields} = unpack($PS_T, $_); + for my $field ( @fields ) { + print "$field: <$process{$field}>\n"; } - print 'line=', pack($PS_T, $pid, $tt, $stat, $time, $command), - "\n"; + print 'line=', pack($PS_T, @process{@fields} ), "\n"; } -We've used C<$$var> in a way that forbidden by C. -That is, we've promoted a string to a scalar variable reference using -symbolic references. This is okay in small programs, but doesn't scale -well. It also only works on global variables, not lexicals. +We've used a hash slice in order to easily handle the fields of each row. +Storing the keys in an array means it's easy to operate on them as a +group or loop over them with for. It also avoids polluting the program +with global variables and using symbolic references. =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? +X X X As of perl5.6, open() autovivifies file and directory handles as references if you pass it an uninitialized scalar variable. @@ -208,6 +242,7 @@ If you want to create many anonymous handles, you should check out the Symbol or IO::Handle modules. =head2 How can I use a filehandle indirectly? +X An indirect filehandle is using something other than a symbol in a place that a filehandle is expected. Here are ways @@ -282,9 +317,9 @@ an expression where you would place the filehandle: That block is a proper block like any other, so you can put more complicated code there. This sends the message out to one of two places: - $ok = -x "/bin/cat"; + $ok = -x "/bin/cat"; print { $ok ? $fd[1] : $fd[2] } "cat stat $ok\n"; - print { $fd[ 1+ ($ok || 0) ] } "cat stat $ok\n"; + print { $fd[ 1+ ($ok || 0) ] } "cat stat $ok\n"; This approach of treating C and C like object methods calls doesn't work for the diamond operator. That's because it's a @@ -303,15 +338,25 @@ It's the syntax of the fundamental operators. Playing the object game doesn't help you at all here. =head2 How can I set up a footer format to be used with write()? +X