Make the point a bit clearer after suggestion from Merijin
[p5sagit/p5-mst-13.2.git] / pod / perlfaq5.pod
index 93a5ffe..4cf2598 100644 (file)
@@ -1,6 +1,6 @@
 =head1 NAME
 
-perlfaq5 - Files and Formats ($Revision: 1.9 $, $Date: 2002/02/11 19:30:21 $)
+perlfaq5 - Files and Formats ($Revision: 1.15 $, $Date: 2002/04/12 02:02:05 $)
 
 =head1 DESCRIPTION
 
@@ -350,37 +350,23 @@ See L<perlform/"Accessing Formatting Internals"> for an swrite() function.
 
 =head2 How can I output my numbers with commas added?
 
-This one will do it for you:
+This one from Benjamin Goldberg will do it for you:
 
-    sub commify {
-        my $number = shift;
-       1 while ($number =~ s/^([-+]?\d+)(\d{3})/$1,$2/);
-       return $number;
-    }
-
-    $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;
+   s/(^[-+]?\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d))/$1,/g;
 
-because you have to put the comma in and then recalculate your
-position.
+or written verbosely:
 
-Alternatively, this code commifies all numbers in a line regardless of
-whether they have decimal portions, are preceded by + or -, or
-whatever:
-
-    # from Andrew Johnson <ajohnson@gpu.srv.ualberta.ca>
-    sub commify {
-       my $input = shift;
-        $input = reverse $input;
-        $input =~ s<(\d\d\d)(?=\d)(?!\d*\.)><$1,>g;
-        return scalar reverse $input;
-    }
+   s/(
+       ^[-+]?            # beginning of number.
+       \d{1,3}?          # first digits before first comma
+       (?=               # followed by, (but not included in the match) :
+          (?>(?:\d{3})+) # some positive multiple of three digits.
+          (?!\d)         # an *exact* multiple, not x * 3 + 1 or whatever.
+       )
+      |                  # or:
+       \G\d{3}           # after the last group, get three digits
+       (?=\d)            # but they have to have more digits after them.
+   )/$1,/xg;
 
 =head2 How can I translate tildes (~) in a filename?
 
@@ -501,35 +487,23 @@ best therefore to use glob() only in list context.
 
 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 the one below.
-It turns 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;
-        s#^([^./])#./$1#;
-        $_ .= "\0";
-       return $_;
-    }
+special. 
 
-    $badpath = "<<<something really wicked   ";
-    $fn = safe_filename($badpath");
-    open(FH, "> $fn") or "couldn't open $badpath: $!";
+The three argument form of open() lets you specify the mode
+separately from the filename.  The open() function treats
+special mode characters and whitespace in the filename as 
+literals
 
-This assumes that you are using POSIX (portable operating systems
-interface) paths.  If you are on a closed, non-portable, proprietary
-system, you may have to adjust the C<"./"> above.
+       open FILE, "<", "  file  ";  # filename is "   file   "
+       open FILE, ">", ">file";     # filename is ">file"
 
-It would be a lot clearer to use sysopen(), though:
+It may be a lot clearer to use sysopen(), though:
 
     use Fcntl;
     $badpath = "<<<something really wicked   ";
     sysopen (FH, $badpath, O_WRONLY | O_CREAT | O_TRUNC)
        or die "can't open $badpath: $!";
 
-For more information, see also the new L<perlopentut> if you have it
-(new for 5.6).
-
 =head2 How can I reliably rename a file?
 
 If your operating system supports a proper mv(1) utility or its functional
@@ -688,14 +662,17 @@ Don't forget them or you'll be quite sorry.
 
 =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> file test 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.
+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> file test 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. Some platforms may not have
+all of these times.  See L<perlport> for details. 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:
 
@@ -780,27 +757,14 @@ you see someone do this:
 
     @lines = <INPUT>;
 
-you should think long and hard about why you need everything loaded
-at once.  It's just not a scalable solution.  You might also find it
-more fun to use the standard DB_File module's $DB_RECNO bindings,
-which allow you to tie an array to a file so that accessing an element
-the array actually accesses the corresponding line in the file.
-
-On very rare occasion, you may have an algorithm that demands that
-the entire file be in memory at once as one scalar.  The simplest solution
-to that is
-
-    $var = `cat $file`;
-
-Being in scalar context, you get the whole thing.  In list context,
-you'd get a list of all the lines:
+you should think long and hard about why you need everything loaded at
+once.  It's just not a scalable solution.  You might also find it more
+fun to use the standard Tie::File module, or the DB_File module's
+$DB_RECNO bindings, which allow you to tie an array to a file so that
+accessing an element the array actually accesses the corresponding
+line in the file.
 
-    @lines = `cat $file`;
-
-This tiny but expedient solution is neat, clean, and portable to
-all systems on which decent tools have been installed.  For those
-who prefer not to use the toolbox, you can of course read the file
-manually, although this makes for more complicated code.
+You can read the entire filehandle contents into a scalar.
 
     {
        local(*INPUT, $/);
@@ -813,6 +777,13 @@ close the file at block exit.  If the file is already open, just use this:
 
     $var = do { local $/; <INPUT> };
 
+For ordinary files you can also use the read function.
+
+       read( INPUT, $var, -s INPUT );
+
+The third argument tests the byte size of the data on the INPUT filehandle
+and reads that many bytes into the buffer $var.
+
 =head2 How can I read in a file by paragraphs?
 
 Use the C<$/> variable (see L<perlvar> for details).  You can either