📄 perlfaq5.1
字号:
.PP.Vb 4\& sub accept_fh {\& my $fh = shift;\& print $fh "Sending to indirect filehandle\en";\& }.Ve.PPOr it can localize a typeglob and use the filehandle directly:.PP.Vb 4\& sub accept_fh {\& local *FH = shift;\& print FH "Sending to localized filehandle\en";\& }.Ve.PPBoth styles work with either objects or typeglobs of real filehandles.(They might also work with strings under some circumstances, but thisis risky.).PP.Vb 2\& accept_fh(*STDOUT);\& accept_fh($handle);.Ve.PPIn the examples above, we assigned the filehandle to a scalar variablebefore using it. That is because only simple scalar variables, notexpressions or subscripts of hashes or arrays, can be used withbuilt-ins like \f(CW\*(C`print\*(C'\fR, \f(CW\*(C`printf\*(C'\fR, or the diamond operator. Usingsomething other than a simple scalar variable as a filehandle isillegal and won't even compile:.PP.Vb 4\& @fd = (*STDIN, *STDOUT, *STDERR);\& print $fd[1] "Type it: "; # WRONG\& $got = <$fd[0]> # WRONG\& print $fd[2] "What was that: $got"; # WRONG.Ve.PPWith \f(CW\*(C`print\*(C'\fR and \f(CW\*(C`printf\*(C'\fR, you get around this by using a block andan expression where you would place the filehandle:.PP.Vb 3\& print { $fd[1] } "funny stuff\en";\& printf { $fd[1] } "Pity the poor %x.\en", 3_735_928_559;\& # Pity the poor deadbeef..Ve.PPThat block is a proper block like any other, so you can put morecomplicated code there. This sends the message out to one of two places:.PP.Vb 3\& $ok = \-x "/bin/cat";\& print { $ok ? $fd[1] : $fd[2] } "cat stat $ok\en";\& print { $fd[ 1+ ($ok || 0) ] } "cat stat $ok\en";.Ve.PPThis approach of treating \f(CW\*(C`print\*(C'\fR and \f(CW\*(C`printf\*(C'\fR 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 \f(CW\*(C`readline\*(C'\fR to read a record justas \f(CW\*(C`<>\*(C'\fR does. Given the initialization shown above for \f(CW@fd\fR, thiswould work, but only because \fIreadline()\fR requires a typeglob. It doesn'twork with objects or strings, which might be a bug we haven't fixed yet..PP.Vb 1\& $got = readline($fd[0]);.Ve.PPLet 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..Sh "How can I set up a footer format to be used with \fIwrite()\fP?".IX Xref "footer".IX Subsection "How can I set up a footer format to be used with write()?"There's no builtin way to do this, but perlform has a couple oftechniques to make it possible for the intrepid hacker..Sh "How can I \fIwrite()\fP into a string?".IX Xref "write, into a string".IX Subsection "How can I write() into a string?"See \*(L"Accessing Formatting Internals\*(R" in perlform for an \f(CW\*(C`swrite()\*(C'\fR function..Sh "How can I open a filehandle to a string? , , ,".IX Xref "string open IO::Scalar filehandle".IX Subsection "How can I open a filehandle to a string? , , ,"(contributed by Peter J. Holzer, hjp\-usenet2@hjp.at).PPSince Perl 5.8.0, you can pass a reference to a scalar instead of thefilename to create a file handle which you can used to read from or write toa string:.PP.Vb 3\& open(my $fh, \*(Aq>\*(Aq, \e$string) or die "Could not open string for writing";\& print $fh "foo\en";\& print $fh "bar\en"; # $string now contains "foo\enbar\en"\&\& open(my $fh, \*(Aq<\*(Aq, \e$string) or die "Could not open string for reading";\& my $x = <$fh>; # $x now contains "foo\en".Ve.PPWith older versions of Perl, the \f(CW\*(C`IO::String\*(C'\fR module provides similarfunctionality..Sh "How can I output my numbers with commas added?".IX Xref "number, commify".IX Subsection "How can I output my numbers with commas added?"(contributed by brian d foy and Benjamin Goldberg).PPYou can use Number::Format to separate places in a number.It handles locale information for those of you who want to insertfull stops instead (or anything else that they want to use,really)..PPThis subroutine will add commas to your number:.PP.Vb 5\& sub commify {\& local $_ = shift;\& 1 while s/^([\-+]?\ed+)(\ed{3})/$1,$2/;\& return $_;\& }.Ve.PPThis regex from Benjamin Goldberg will add commas to numbers:.PP.Vb 1\& s/(^[\-+]?\ed+?(?=(?>(?:\ed{3})+)(?!\ed))|\eG\ed{3}(?=\ed))/$1,/g;.Ve.PPIt is easier to see with comments:.PP.Vb 11\& s/(\& ^[\-+]? # beginning of number.\& \ed+? # first digits before first comma\& (?= # followed by, (but not included in the match) :\& (?>(?:\ed{3})+) # some positive multiple of three digits.\& (?!\ed) # an *exact* multiple, not x * 3 + 1 or whatever.\& )\& | # or:\& \eG\ed{3} # after the last group, get three digits\& (?=\ed) # but they have to have more digits after them.\& )/$1,/xg;.Ve.Sh "How can I translate tildes (~) in a filename?".IX Xref "tilde tilde expansion".IX Subsection "How can I translate tildes (~) in a filename?"Use the <> (\fIglob()\fR) operator, documented in perlfunc. Olderversions of Perl require that you have a shell installed that grokstildes. Recent perl versions have this feature built in. TheFile::KGlob module (available from \s-1CPAN\s0) gives more portable globfunctionality..PPWithin Perl, you may use this directly:.PP.Vb 11\& $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;.Ve.Sh "How come when I open a file read-write it wipes it out?".IX Xref "clobber read-write clobbering truncate truncating".IX Subsection "How come when I open a file read-write it wipes it out?"Because you're using something like this, which truncates the file and\&\fIthen\fR gives you read-write access:.PP.Vb 1\& open(FH, "+> /path/name"); # WRONG (almost always).Ve.PPWhoops. You should instead use this, which will fail if the filedoesn't exist..PP.Vb 1\& open(FH, "+< /path/name"); # open for update.Ve.PPUsing \*(L">\*(R" always clobbers or creates. Using \*(L"<\*(R" never doeseither. The \*(L"+\*(R" doesn't change this..PPHere are examples of many kinds of file opens. Those using \fIsysopen()\fRall assume.PP.Vb 1\& use Fcntl;.Ve.PPTo open file for reading:.PP.Vb 2\& open(FH, "< $path") || die $!;\& sysopen(FH, $path, O_RDONLY) || die $!;.Ve.PPTo open file for writing, create new file if needed or else truncate old file:.PP.Vb 3\& 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 $!;.Ve.PPTo open file for writing, create new file, file must not exist:.PP.Vb 2\& sysopen(FH, $path, O_WRONLY|O_EXCL|O_CREAT) || die $!;\& sysopen(FH, $path, O_WRONLY|O_EXCL|O_CREAT, 0666) || die $!;.Ve.PPTo open file for appending, create if necessary:.PP.Vb 3\& 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 $!;.Ve.PPTo open file for appending, file must exist:.PP.Vb 1\& sysopen(FH, $path, O_WRONLY|O_APPEND) || die $!;.Ve.PPTo open file for update, file must exist:.PP.Vb 2\& open(FH, "+< $path") || die $!;\& sysopen(FH, $path, O_RDWR) || die $!;.Ve.PPTo open file for update, create file if necessary:.PP.Vb 2\& sysopen(FH, $path, O_RDWR|O_CREAT) || die $!;\& sysopen(FH, $path, O_RDWR|O_CREAT, 0666) || die $!;.Ve.PPTo open file for update, file must not exist:.PP.Vb 2\& sysopen(FH, $path, O_RDWR|O_EXCL|O_CREAT) || die $!;\& sysopen(FH, $path, O_RDWR|O_EXCL|O_CREAT, 0666) || die $!;.Ve.PPTo open a file without blocking, creating if necessary:.PP.Vb 2\& sysopen(FH, "/foo/somefile", O_WRONLY|O_NDELAY|O_CREAT)\& or die "can\*(Aqt open /foo/somefile: $!":.Ve.PPBe warned that neither creation nor deletion of files is guaranteed tobe an atomic operation over \s-1NFS\s0. That is, two processes might bothsuccessfully create or unlink the same file! Therefore O_EXCLisn't as exclusive as you might wish..PPSee also the new perlopentut if you have it (new for 5.6)..ie n .Sh "Why do I sometimes get an ""Argument list too long"" when I use <*>?".el .Sh "Why do I sometimes get an ``Argument list too long'' when I use <*>?".IX Xref "argument list too long".IX Subsection "Why do I sometimes get an Argument list too long when I use <*>?"The \f(CW\*(C`<>\*(C'\fR operator performs a globbing operation (see above).In Perl versions earlier than v5.6.0, the internal \fIglob()\fR operator forks\&\fIcsh\fR\|(1) to do the actual glob expansion, butcsh can't handle more than 127 items and so gives the error message\&\f(CW\*(C`Argument list too long\*(C'\fR. People who installed tcsh as csh won'thave this problem, but their users may be surprised by it..PPTo get around this, either upgrade to Perl v5.6.0 or later, do the globyourself with \fIreaddir()\fR and patterns, or use a module like File::KGlob,one that doesn't use the shell to do globbing..Sh "Is there a leak/bug in \fIglob()\fP?".IX Xref "glob".IX Subsection "Is there a leak/bug in glob()?"Due to the current implementation on some operating systems, when youuse the \fIglob()\fR function or its angle-bracket alias in a scalarcontext, you may cause a memory leak and/or unpredictable behavior. It'sbest therefore to use \fIglob()\fR only in list context..ie n .Sh "How can I open a file with a leading "">"" or trailing blanks?".el .Sh "How can I open a file with a leading ``>'' or trailing blanks?".IX Xref "filename, special characters".IX Subsection "How can I open a file with a leading > or trailing blanks?"(contributed by Brian McCauley).PPThe special two argument form of Perl's \fIopen()\fR function ignorestrailing blanks in filenames and infers the mode from certain leadingcharacters (or a trailing \*(L"|\*(R"). In older versions of Perl this was theonly version of \fIopen()\fR and so it is prevalent in old code and books..PPUnless you have a particular reason to use the two argument form youshould use the three argument form of \fIopen()\fR which does not treat anycharacters in the filename as special..PP.Vb 2\& open FILE, "<", " file "; # filename is " file "\& open FILE, ">", ">file"; # filename is ">file".Ve.Sh "How can I reliably rename a file?".IX Xref "rename mv move file, rename ren".IX Subsection "How can I reliably rename a file?"If your operating system supports a proper \fImv\fR\|(1) utility or itsfunctional equivalent, this works:.PP.Vb 1\& rename($old, $new) or system("mv", $old, $new);.Ve.PPIt may be more portable to use the File::Copy module instead.You just copy to the new file to the new name (checking returnvalues), then delete the old one. This isn't really the samesemantically as a \fIrename()\fR, which preserves meta-information likepermissions, timestamps, inode info, etc..PP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -