This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
consting for .c files in tests
[perl5.git] / pod / perlfaq5.pod
index 98be1b0..821664d 100644 (file)
@@ -1,6 +1,6 @@
 =head1 NAME
 
-perlfaq5 - Files and Formats ($Revision: 3606 $)
+perlfaq5 - Files and Formats ($Revision: 10126 $)
 
 =head1 DESCRIPTION
 
@@ -10,62 +10,221 @@ formats, and footers.
 =head2 How do I flush/unbuffer an output filehandle?  Why must I do this?
 X<flush> X<buffer> X<unbuffer> X<autoflush>
 
-Perl does not support truly unbuffered output (except
-insofar as you can C<syswrite(OUT, $char, 1)>), although it
-does support is "command buffering", in which a physical
-write is performed after every output command.
-
-The C standard I/O library (stdio) normally buffers
-characters sent to devices so that there isn't a system call
-for each byte. In most stdio implementations, the type of
-output buffering and the size of the buffer varies according
-to the type of device. Perl's print() and write() functions
-normally buffer output, while syswrite() bypasses buffering
-all together.
-
-If you want your output to be sent immediately when you
-execute print() or write() (for instance, for some network
-protocols), you must set the handle's autoflush flag. This
-flag is the Perl variable $| and when it is set to a true
-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
+Perl does not support truly unbuffered output (except insofar as you
+can C<syswrite(OUT, $char, 1)>), although it does support is "command
+buffering", in which a physical write is performed after every output
+command.
+
+The C standard I/O library (stdio) normally buffers characters sent to
+devices so that there isn't a system call for each byte. In most stdio
+implementations, the type of output buffering and the size of the
+buffer varies according to the type of device. Perl's C<print()> and
+C<write()> functions normally buffer output, while C<syswrite()>
+bypasses buffering all together.
+
+If you want your output to be sent immediately when you execute
+C<print()> or C<write()> (for instance, for some network protocols),
+you must set the handle's autoflush flag. This flag is the Perl
+variable C<$|> and when it is set to a true value, Perl will flush the
+handle's buffer after each C<print()> or C<write()>. Setting C<$|>
+affects buffering only for the currently selected default filehandle.
+You choose this handle with the one argument C<select()> call (see
 L<perlvar/$E<verbar>> and L<perlfunc/select>).
 
-Use select() to choose the desired handle, then set its
+Use C<select()> to choose the desired handle, then set its
 per-filehandle variables.
 
        $old_fh = select(OUTPUT_HANDLE);
        $| = 1;
        select($old_fh);
 
-Some idioms can handle this in a single statement:
-
-       select((select(OUTPUT_HANDLE), $| = 1)[0]);
-
-       $| = 1, select $_ for select OUTPUT_HANDLE;
-
 Some modules offer object-oriented access to handles and their
-variables, although they may be overkill if this is the only
-thing you do with them.  You can use IO::Handle:
+variables, although they may be overkill if this is the only thing you
+do with them.  You can use C<IO::Handle>:
 
        use IO::Handle;
-       open(DEV, ">/dev/printer");   # but is this?
-       DEV->autoflush(1);
+       open my( $printer ), ">", "/dev/printer");   # but is this?
+       $printer->autoflush(1);
 
-or IO::Socket:
+or C<IO::Socket> (which inherits from C<IO::Handle>):
 
        use IO::Socket;           # this one is kinda a pipe?
        my $sock = IO::Socket::INET->new( 'www.example.com:80' );
 
        $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?
+You can also flush an C<IO::Handle> object without setting
+C<autoflush>. Call the C<flush> method to flush the buffer yourself:
+
+       use IO::Handle;
+       open my( $printer ), ">", "/dev/printer"); 
+       $printer->flush; # one time flush
+
+       
+=head2 How do I change, delete, or insert a line in a file, or append to the beginning of a file?
 X<file, editing>
 
-Use the Tie::File module, which is included in the standard
-distribution since Perl 5.8.0.
+(contributed by brian d foy)
+
+The basic idea of inserting, changing, or deleting a line from a text
+file involves reading and printing the file to the point you want to
+make the change, making the change, then reading and printing the rest
+of the file. Perl doesn't provide random access to lines (especially
+since the record input separator, C<$/>, is mutable), although modules
+such as C<Tie::File> can fake it.
+
+A Perl program to do these tasks takes the basic form of opening a
+file, printing its lines, then closing the file:
+
+       open my $in,  '<',  $file      or die "Can't read old file: $!";
+       open my $out, '>', "$file.new" or die "Can't write new file: $!";
+
+       while( <$in> )
+               {
+               print $out $_;
+               }
+
+   close $out;
+
+Within that basic form, add the parts that you need to insert, change,
+or delete lines.
+
+To prepend lines to the beginning, print those lines before you enter
+the loop that prints the existing lines.
+
+       open my $in,  '<',  $file      or die "Can't read old file: $!";
+       open my $out, '>', "$file.new" or die "Can't write new file: $!";
+
+       print "# Add this line to the top\n"; # <--- HERE'S THE MAGIC
+
+       while( <$in> )
+               {
+               print $out $_;
+               }
+
+   close $out;
+
+To change existing lines, insert the code to modify the lines inside
+the C<while> loop. In this case, the code finds all lowercased
+versions of "perl" and uppercases them. The happens for every line, so
+be sure that you're supposed to do that on every line!
+
+       open my $in,  '<',  $file      or die "Can't read old file: $!";
+       open my $out, '>', "$file.new" or die "Can't write new file: $!";
+
+       print "# Add this line to the top\n";
+
+       while( <$in> )
+               {
+               s/\b(perl)\b/Perl/g;
+               print $out $_;
+               }
+
+   close $out;
+
+To change only a particular line, the input line number, C<$.>, is
+useful. First read and print the lines up to the one you  want to
+change. Next, read the single line you want to change, change it, and
+print it. After that, read the rest of the lines and print those:
+
+       while( <$in> )   # print the lines before the change
+               {
+               print $out $_;
+               last if $. == 4; # line number before change
+               }
+
+       my $line = <$in>;
+       $line =~ s/\b(perl)\b/Perl/g;
+       print $out $line;
+
+       while( <$in> )   # print the rest of the lines
+               {
+               print $out $_;
+               }
+               
+To skip lines, use the looping controls. The C<next> in this example
+skips comment lines, and the C<last> stops all processing once it
+encounters either C<__END__> or C<__DATA__>.
+
+       while( <$in> )
+               {
+               next if /^\s+#/;             # skip comment lines
+               last if /^__(END|DATA)__$/;  # stop at end of code marker
+               print $out $_;
+               }
+
+Do the same sort of thing to delete a particular line by using C<next>
+to skip the lines you don't want to show up in the output. This
+example skips every fifth line:
+
+       while( <$in> )
+               {
+               next unless $. % 5;
+               print $out $_;
+               }
+
+If, for some odd reason, you really want to see the whole file at once
+rather than processing line by line, you can slurp it in (as long as
+you can fit the whole thing in memory!):
+
+       open my $in,  '<',  $file      or die "Can't read old file: $!"
+       open my $out, '>', "$file.new" or die "Can't write new file: $!";
+
+       my @lines = do { local $/; <$in> }; # slurp!
+
+               # do your magic here
+
+       print $out @lines;
+
+Modules such as C<File::Slurp> and C<Tie::File> can help with that
+too. If you can, however, avoid reading the entire file at once. Perl
+won't give that memory back to the operating system until the process
+finishes.
+
+You can also use Perl one-liners to modify a file in-place. The
+following changes all 'Fred' to 'Barney' in F<inFile.txt>, overwriting
+the file with the new contents. With the C<-p> switch, Perl wraps a
+C<while> loop around the code you specify with C<-e>, and C<-i> turns
+on in-place editing. The current line is in C<$_>. With C<-p>, Perl
+automatically prints the value of C<$_> at the end of the loop. See
+L<perlrun> for more details.
+
+       perl -pi -e 's/Fred/Barney/' inFile.txt
+
+To make a backup of C<inFile.txt>, give C<-i> a file extension to add:
+
+       perl -pi.bak -e 's/Fred/Barney/' inFile.txt
+
+To change only the fifth line, you can add a test checking C<$.>, the
+input line number, then only perform the operation when the test
+passes:
+
+       perl -pi -e 's/Fred/Barney/ if $. == 5' inFile.txt
+
+To add lines before a certain line, you can add a line (or lines!)
+before Perl prints C<$_>:
+
+       perl -pi -e 'print "Put before third line\n" if $. == 3' inFile.txt
+
+You can even add a line to the beginning of a file, since the current
+line prints at the end of the loop:
+
+       perl -pi -e 'print "Put before first line\n" if $. == 1' inFile.txt
+
+To insert a line after one already in the file, use the C<-n> switch.
+It's just like C<-p> except that it doesn't print C<$_> at the end of
+the loop, so you have to do that yourself. In this case, print C<$_>
+first, then print the line that you want to add.
+
+       perl -ni -e 'print; print "Put after fifth line\n" if $. == 5' inFile.txt
+
+To delete lines, only print the ones that you want.
+
+       perl -ni -e 'print unless /d/' inFile.txt
+
+               ... or ...
+
+       perl -pi -e 'next unless /d/' inFile.txt
 
 =head2 How do I count the number of lines in a file?
 X<file, counting lines> X<lines> X<line>
@@ -163,24 +322,25 @@ temporary files in one process, use a counter:
        BEGIN {
        use Fcntl;
        my $temp_dir = -d '/tmp' ? '/tmp' : $ENV{TMPDIR} || $ENV{TEMP};
-       my $base_name = sprintf("%s/%d-%d-0000", $temp_dir, $$, time());
+       my $base_name = sprintf "%s/%d-%d-0000", $temp_dir, $$, time;
 
        sub temp_file {
                local *FH;
                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);
+               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) ) {
+                       return (*FH, $base_name);
+                       }
+               else {
+                       return ();
+                       }
                }
-
-       if (defined(fileno(FH))
-               return (*FH, $base_name);
-           } 
-       else {
-               return ();
-           }
-       }
+               
        }
 
 =head2 How can I manipulate fixed-record-length files?
@@ -215,7 +375,7 @@ 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? 
+=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<filehandle, local> X<filehandle, passing> X<filehandle, reference>
 
 As of perl5.6, open() autovivifies file and directory handles
@@ -233,17 +393,16 @@ and use them in the place of named handles.
 
 If you like, you can store these filehandles in an array or a hash.
 If you access them directly, they aren't simple scalars and you
-need to give C<print> a little help by placing the filehandle 
+need to give C<print> a little help by placing the filehandle
 reference in braces. Perl can only figure it out on its own when
 the filehandle reference is a simple scalar.
 
        my @fhs = ( $fh1, $fh2, $fh3 );
-       
+
        for( $i = 0; $i <= $#fhs; $i++ ) {
                print {$fhs[$i]} "just another Perl answer, \n";
                }
 
-
 Before perl5.6, you had to deal with various typeglob idioms
 which you may see in older code.
 
@@ -362,8 +521,27 @@ techniques to make it possible for the intrepid hacker.
 =head2 How can I write() into a string?
 X<write, into a string>
 
-See L<perlform/"Accessing Formatting Internals"> for an swrite() function.
+See L<perlform/"Accessing Formatting Internals"> for an C<swrite()> function.
+
+=head2 How can I open a filehandle to a string?
+X<string>, X<open>, X<IO::Scalar>, X<filehandle>
+
+(contributed by Peter J. Holzer, hjp-usenet2@hjp.at)
 
+Since Perl 5.8.0, you can pass a reference to a scalar instead of the
+filename to create a file handle which you can used to read from or write to
+a string:
+
+       open(my $fh, '>', \$string) or die "Could not open string for writing";
+       print $fh "foo\n";
+       print $fh "bar\n";      # $string now contains "foo\nbar\n"
+
+       open(my $fh, '<', \$string) or die "Could not open string for reading";
+       my $x = <$fh>;  # $x now contains "foo\n"
+
+With older versions of Perl, the C<IO::String> module provides similar
+functionality.
+    
 =head2 How can I output my numbers with commas added?
 X<number, commify>
 
@@ -531,7 +709,7 @@ only version of open() and so it is prevalent in old code and books.
 
 Unless you have a particular reason to use the two argument form you
 should use the three argument form of open() which does not treat any
-charcters in the filename as special.
+characters in the filename as special.
 
        open FILE, "<", "  file  ";  # filename is "   file   "
        open FILE, ">", ">file";     # filename is ">file"
@@ -618,7 +796,7 @@ atomic test-and-set instruction.   In theory, this "ought" to work:
 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 link() have been suggested, but
-these tend to involve busy-wait, which is also subdesirable.
+these tend to involve busy-wait, which is also less than desirable.
 
 =head2 I still don't get locking.  I just want to increment the number in the file.  How can I do this?
 X<counter> X<file, counter>
@@ -657,7 +835,7 @@ then that is what you should do.
 
 If you know you are only going to use a system that does correctly
 implement appending (i.e. not Win32) then you can omit the seek() from
-the above code.
+the code in the previous answer.
 
 If you know you are only writing code to run on an OS and filesystem that
 does implement append mode correctly (a local filesystem on a modern
@@ -876,7 +1054,7 @@ turns off echo processing as well.
                $term->setcc(VTIME, 1);
                $term->setattr($fd_stdin, TCSANOW);
                }
-       
+
        sub cooked {
                $term->setlflag($oterm);
                $term->setcc(VTIME, 0);
@@ -967,7 +1145,7 @@ FIONREAD requires a filehandle connected to a stream, meaning that sockets,
 pipes, and tty devices work, but I<not> files.
 
 =head2 How do I do a C<tail -f> in perl?
-X<tail>
+X<tail> X<IO::Handle> X<File::Tail> X<clearerr>
 
 First try
 
@@ -975,7 +1153,7 @@ First try
 
 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.
+next C<< <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:
@@ -988,12 +1166,11 @@ then you need something more like this:
          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.
+If this still doesn't work, look into the C<clearerr> method
+from C<IO::Handle>, which resets the error and end-of-file states
+on the handle.
 
-There's also a File::Tail module from CPAN.
+There's also a C<File::Tail> module from CPAN.
 
 =head2 How do I dup() a filehandle in Perl?
 X<dup>
@@ -1017,23 +1194,30 @@ a copied one.
 Error checking, as always, has been left as an exercise for the reader.
 
 =head2 How do I close a file descriptor by number?
-X<file, closing file descriptors>
+X<file, closing file descriptors> X<POSIX> X<close>
+
+If, for some reason, you have a file descriptor instead of a
+filehandle (perhaps you used C<POSIX::open>), you can use the
+C<close()> function from the C<POSIX> module:
 
-This should rarely be necessary, as the Perl close() function is to be
+       use POSIX ();
+       
+       POSIX::close( $fd );
+       
+This should rarely be necessary, as the Perl C<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
+numeric descriptor as with C<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;
 
-Or, just use the fdopen(3S) feature of open():
+Or, just use the fdopen(3S) feature of C<open()>:
 
        {
-       local *F;
-       open F, "<&=$fd" or die "Cannot reopen fd=$fd: $!";
-       close F;
+       open my( $fh ), "<&=$fd" or die "Cannot reopen fd=$fd: $!";
+       close $fh;
        }
 
 =head2 Why can't I use "C:\temp\foo" in DOS paths?  Why doesn't `C:\temp\foo.exe` work?
@@ -1122,15 +1306,15 @@ If your array contains lines, just print them:
 
 =head1 REVISION
 
-Revision: $Revision: 3606 $
+Revision: $Revision: 10126 $
 
-Date: $Date: 2006-03-06 12:05:47 +0100 (lun, 06 mar 2006) $
+Date: $Date: 2007-10-27 21:29:20 +0200 (Sat, 27 Oct 2007) $
 
 See L<perlfaq> for source control details and availability.
 
 =head1 AUTHOR AND COPYRIGHT
 
-Copyright (c) 1997-2006 Tom Christiansen, Nathan Torkington, and
+Copyright (c) 1997-2007 Tom Christiansen, Nathan Torkington, and
 other authors as noted. All rights reserved.
 
 This documentation is free; you can redistribute it and/or modify it