⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 perlfaq5.pod

📁 MSYS在windows下模拟了一个类unix的终端
💻 POD
📖 第 1 页 / 共 3 页
字号:
This approach of treating C<print> and C<printf> like object methodscalls doesn't work for the diamond operator.  That's because it's areal operator, not just a function with a comma-less argument.  Assumingyou've been storing typeglobs in your structure as we did above, youcan use the built-in function named C<readline> to reads a record justas C<< <> >> does.  Given the initialization shown above for @fd, thiswould work, but only because readline() require a typeglob.  It doesn'twork with objects or strings, which might be a bug we haven't fixed yet.    $got = readline($fd[0]);Let it be noted that the flakiness of indirect filehandles is notrelated to whether they're strings, typeglobs, objects, or anything else.It's the syntax of the fundamental operators.  Playing the objectgame doesn't help you at all here.=head2 How can I set up a footer format to be used with write()?There's no builtin way to do this, but L<perlform> has a couple oftechniques to make it possible for the intrepid hacker.=head2 How can I write() into a string?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:    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.2331You can't just:    s/^([-+]?\d+)(\d{3})/$1,$2/g;because you have to put the comma in and then recalculate yourposition.Alternatively, this code commifies all numbers in a line regardless ofwhether they have decimal portions, are preceded by + or -, orwhatever:    # 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;    }=head2 How can I translate tildes (~) in a filename?Use the <> (glob()) operator, documented in L<perlfunc>.  Olderversions of Perl require that you have a shell installed that grokstildes.  Recent perl versions have this feature built in. TheGlob::KGlob module (available from CPAN) gives more portable globfunctionality.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 a file read-write it wipes it out?Because you're using something like this, which truncates the file andI<then> gives you read-write access:    open(FH, "+> /path/name");		# WRONG (almost always)Whoops.  You should instead use this, which will fail if the filedoesn't exist.      open(FH, "+< /path/name");  	# open for updateUsing ">" always clobbers or creates.  Using "<" never doeseither.  The "+" doesn't change this.Here are examples of many kinds of file opens.  Those using sysopen()all assume    use Fcntl;To open file for reading:    open(FH, "< $path")                                 || die $!;    sysopen(FH, $path, O_RDONLY)                        || die $!;To open file for writing, create new file if needed or else truncate old file:    open(FH, "> $path") || die $!;    sysopen(FH, $path, O_WRONLY|O_TRUNC|O_CREAT)        || die $!;    sysopen(FH, $path, O_WRONLY|O_TRUNC|O_CREAT, 0666)  || die $!;To open file for writing, create new file, file must not exist:    sysopen(FH, $path, O_WRONLY|O_EXCL|O_CREAT)         || die $!;    sysopen(FH, $path, O_WRONLY|O_EXCL|O_CREAT, 0666)   || die $!;To open file for appending, create if necessary:    open(FH, ">> $path") || die $!;    sysopen(FH, $path, O_WRONLY|O_APPEND|O_CREAT)       || die $!;    sysopen(FH, $path, O_WRONLY|O_APPEND|O_CREAT, 0666) || die $!;To open file for appending, file must exist:    sysopen(FH, $path, O_WRONLY|O_APPEND)               || die $!;To open file for update, file must exist:    open(FH, "+< $path")                                || die $!;    sysopen(FH, $path, O_RDWR)                          || die $!;To open file for update, create file if necessary:    sysopen(FH, $path, O_RDWR|O_CREAT)                  || die $!;    sysopen(FH, $path, O_RDWR|O_CREAT, 0666)            || die $!;To open file for update, file must not exist:    sysopen(FH, $path, O_RDWR|O_EXCL|O_CREAT)           || die $!;    sysopen(FH, $path, O_RDWR|O_EXCL|O_CREAT, 0666)     || die $!;To open a file without blocking, creating if necessary:    sysopen(FH, "/tmp/somefile", O_WRONLY|O_NDELAY|O_CREAT)	    or die "can't open /tmp/somefile: $!":Be warned that neither creation nor deletion of files is guaranteed tobe an atomic operation over NFS.  That is, two processes might bothsuccessfully create or unlink the same file!  Therefore O_EXCLisn't as exclusive as you might wish.See also the new L<perlopentut> if you have it (new for 5.6).=head2 Why do I sometimes get an "Argument list too long" when I use <*>?The C<< <> >> operator performs a globbing operation (see above).In Perl versions earlier than v5.6.0, the internal glob() operator forkscsh(1) to do the actual glob expansion, butcsh can't handle more than 127 items and so gives the error messageC<Argument list too long>.  People who installed tcsh as csh won'thave this problem, but their users may be surprised by it.To get around this, either upgrade to Perl v5.6.0 or later, do the globyourself with readdir() 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 youuse the glob() function or its angle-bracket alias in a scalarcontext, you may cause a memory leak and/or unpredictable behavior.  It'sbest therefore to use glob() only in list context.=head2 How can I open a file with a leading ">" or trailing blanks?Normally perl ignores trailing blanks in filenames, and interpretscertain leading characters (or a trailing "|") to mean somethingspecial.  To avoid this, you might want to use a routine like the one below.It turns incomplete pathnames into explicit relative ones, and tacks atrailing null byte on the name to make perl leave it alone:    sub safe_filename {	local $_  = shift;        s#^([^./])#./$1#;        $_ .= "\0";	return $_;    }    $badpath = "<<<something really wicked   ";    $fn = safe_filename($badpath");    open(FH, "> $fn") or "couldn't open $badpath: $!";This assumes that you are using POSIX (portable operating systemsinterface) paths.  If you are on a closed, non-portable, proprietarysystem, you may have to adjust the C<"./"> above.It would 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?Well, usually you just use Perl's rename() function.  That may notwork everywhere, though, particularly when renaming files across file systems.Some sub-Unix systems have broken ports that corrupt the semantics ofrename()--for example, WinNT does this right, but Win95 and Win98are broken.  (The last two parts are not surprising, but the first is. :-)If your operating system supports a proper mv(1) program or its moralequivalent, this works:    rename($old, $new) or system("mv", $old, $new);It may be more compelling to use the File::Copy module instead.  Youjust copy to the new file to the new name (checking return values),then delete the old one.  This isn't really the same semantically as areal rename(), though, which preserves metainformation likepermissions, timestamps, inode info, etc.Newer versions of File::Copy exports a move() function.=head2 How can I lock a file?Perl's builtin flock() function (see L<perlfunc> for details) will callflock(2) if that exists, fcntl(2) if it doesn't (on perl version 5.004 andlater), 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 1Produces a fatal error if none of the three system calls (or theirclose equivalent) exists.=item 2lockf(3) does not provide shared locking, and requires that thefilehandle be open for writing (or appending, or read/writing).=item 3Some versions of flock() can't lock files over a network (e.g. on NFS filesystems), so you'd need to force the use of fcntl(2) when you build Perl.But even this is dubious at best.  See the flock entry of L<perlfunc>and the F<INSTALL> file in the source distribution for information onbuilding Perl to do this.Two potentially non-obvious but traditional flock semantics are thatit waits indefinitely until the lock is granted, and that its locks areI<merely advisory>.  Such discretionary locks are more flexible, butoffer fewer guarantees.  This means that files locked with flock() maybe modified by programs that do not also use flock().  Cars that stopfor red lights get on well with each other, but not with cars that don'tstop for red lights.  See the perlport manpage, your port's specificdocumentation, or your system-specific local manpages for details.  It'sbest to assume traditional behavior if you're writing portable programs.(If you're not, you should as always feel perfectly free to writefor your own system's idiosyncrasies (sometimes called "features").Slavish adherence to portability concerns shouldn't get in the way ofyour getting your job done.)For more information on file locking, see also L<perlopentut/"File Locking"> if you have it (new for 5.6).=back=head2 Why 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 CODEThis is a classic race condition: you take two steps to do somethingwhich must be done in one.  That's why computer hardware provides anatomic test-and-set instruction.   In theory, this "ought" to work:    sysopen(FH, "file.lock", O_WRONLY|O_EXCL|O_CREAT)		or die "can't open  file.lock: $!":except that lamentably, file creation (and deletion) is not atomicover NFS, so this won't work (at least, not every time) over the net.Various schemes involving link() have been suggested, butthese 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?They don't count number of hits, they're a waste of time, and they serveonly to stroke the writer's vanity.  It's better to pick a random number;they're more realistic.Anyway, this is what you can do if you can't help yourself.    use Fcntl qw(:DEFAULT :flock);    sysopen(FH, "numfile", O_RDWR|O_CREAT) 	 or die "can't open numfile: $!";    flock(FH, LOCK_EX) 				 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: $!";    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 assimple as this works:    perl -i -pe 's{window manager}{window mangler}g' /usr/bin/emacsHowever, if you have fixed sized records, then you might do something morelike 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, -$RECSIZE, 1);    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.=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>.  Theseretrieve the age of the file (measured against the start-time of yourprogram) 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 thisinto human-readable form.Here's an example:    $write_secs = (stat($file))[9];    printf "file %s updated at %s\n", $file,	scalar localtime($write_secs);If you prefer something more legible, use the File::stat module(part of the standard distribution in version 5.004 and later):    # error checking left as an exercise for reader.    use File::stat;    use Time::localtime;    $date_string = ctime(stat($file)->mtime);    print "file $file updated at $date_string\n";The POSIX::strftime() approach has the benefit of being,in theory, independent of the current locale.  See L<perllocale>for details.=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 theread and write times from its first argument to all the restof 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, as usual, left as an exercise for the reader.Note that utime() currently doesn't work correctly with Win95/NTports.  A bug has been reported.  Check it carefully before usingutime() 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'seasiest to use the tee(1) program if you have it, and let it take careof the multiplexing:    open (FH, "| tee file1 file2 file3");Or even:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -