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

📄 perlfaq5.html

📁 《Perl 5教程》及《perl常问问题集》
💻 HTML
📖 第 1 页 / 共 3 页
字号:
    <HTML> 	<HEAD> 	    <TITLE>perlfaq5</TITLE> 	</HEAD>	<BODY background="gback.jpg"><H1>perlfaq5 - perl常问问题集,第五篇</H1><p><p><H2><A NAME="INDEX">目录</A></H2><!-- INDEX BEGIN --><UL>	<LI><A HREF="#NAME">NAME</A>	<LI><A HREF="#DESCRIPTION">DESCRIPTION</A>	<UL>		<LI><A HREF="#How_do_I_flush_unbuffer_a_fileha">How do I flush/unbuffer a filehandle?  Why must I do this?</A>		<LI><A HREF="#How_do_I_change_one_line_in_a_fi">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?</A>		<LI><A HREF="#How_do_I_count_the_number_of_lin">How do I count the number of lines in a file?</A>		<LI><A HREF="#How_do_I_make_a_temporary_file_n">How do I make a temporary file name?</A>		<LI><A HREF="#How_can_I_manipulate_fixed_recor">How can I manipulate fixed-record-length files?</A>		<LI><A HREF="#How_can_I_make_a_filehandle_loca">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?</A>		<LI><A HREF="#How_can_I_set_up_a_footer_format">How can I set up a footer format to be used with write()?</A>		<LI><A HREF="#How_can_I_write_into_a_string_">How can I write() into a string?</A>		<LI><A HREF="#How_can_I_output_my_numbers_with">How can I output my numbers with commas added?</A>		<LI><A HREF="#How_can_I_translate_tildes_i">How can I translate tildes (~) in a filename?</A>		<LI><A HREF="#How_come_when_I_open_the_file_re">How come when I open the file read-write it wipes it out?</A>		<LI><A HREF="#Why_do_I_sometimes_get_an_Argum">Why do I sometimes get an "Argument list too long" when I use <*>?</A>		<LI><A HREF="#Is_there_a_leak_bug_in_glob_">Is there a leak/bug in glob()?</A>		<LI><A HREF="#How_can_I_open_a_file_with_a_lea">How can I open a file with a leading "&gt;" or trailing blanks?</A>		<LI><A HREF="#How_can_I_reliably_rename_a_file">How can I reliably rename a file?</A>		<LI><A HREF="#How_can_I_lock_a_file_">How can I lock a file?</A>		<LI><A HREF="#What_can_t_I_just_open_FH_fil">What can't I just open(FH, ">file.lock")?</A>		<LI><A HREF="#I_still_don_t_get_locking_I_jus">I still don't get locking.  I just want to increment the number in the file.  How can I do this?</A>		<LI><A HREF="#How_do_I_randomly_update_a_binar">How do I randomly update a binary file?</A>		<LI><A HREF="#How_do_I_get_a_file_s_timestamp_">How do I get a file's timestamp in perl?</A>		<LI><A HREF="#How_do_I_set_a_file_s_timestamp_">How do I set a file's timestamp in perl?</A>		<LI><A HREF="#How_do_I_print_to_more_than_one_">How do I print to more than one file at once?</A>		<LI><A HREF="#How_can_I_read_in_a_file_by_para">How can I read in a file by paragraphs?</A>		<LI><A HREF="#How_can_I_read_a_single_characte">How can I read a single character from a file?  From the keyboard?</A>		<LI><A HREF="#How_can_I_tell_if_there_s_a_char">How can I tell if there's a character waiting on a filehandle?</A>		<LI><A HREF="#How_do_I_open_a_file_without_blo">How do I open a file without blocking?</A>		<LI><A HREF="#How_do_I_create_a_file_only_if_i">How do I create a file only if it doesn't exist?</A>		<LI><A HREF="#How_do_I_do_a_C_tail_f_in_perl">How do I do a <CODE>tail -f</CODE> in perl?</A>		<LI><A HREF="#How_do_I_dup_a_filehandle_in_P">How do I dup() a filehandle in Perl?</A>		<LI><A HREF="#How_do_I_close_a_file_descriptor">How do I close a file descriptor by number?</A>		<LI><A HREF="#Why_can_t_I_use_C_temp_foo_in">Why can't I use "C:\temp\foo" in DOS paths?  What doesn't `C:\temp\foo.exe` work?</A>		<LI><A HREF="#Why_doesn_t_glob_get_all_">Why doesn't glob("*.*") get all the files?</A>		<LI><A HREF="#Why_does_Perl_let_me_delete_read">Why does Perl let me delete read-only files?  Why does <CODE>-i</CODE> clobber protected files?  Isn't this a bug in Perl?</A>		<LI><A HREF="#How_do_I_select_a_random_line_fr">How do I select a random line from a file?</A>	</UL>	<LI><A HREF="#AUTHOR_AND_COPYRIGHT">AUTHOR AND COPYRIGHT</A></UL><!-- INDEX END --><HR><P><H2><A NAME="NAME">NAME</A></H2>perlfaq5 - Files and Formats ($Revision: 1.22 $, $Date: 1997/04/24 22:44:02$)<P><P><HR><H2><A NAME="DESCRIPTION">DESCRIPTION</A></H2>This section deals with <FONT SIZE=-1>I/O</FONT> and the ``f'' issues: filehandles, flushing,formats, and footers.<P><P><HR><H3><A NAME="How_do_I_flush_unbuffer_a_fileha">How do I flush/unbuffer a filehandle?  Why must I do this?</A></H3>The <FONT SIZE=-1>C</FONT> standard <FONT SIZE=-1>I/O</FONT> library (stdio) normally buffers characters sent to devices. This is done for efficiency reasons, so that there isn't a system call for each byte. Any time you use <CODE>print()</CODE> or <CODE>write()</CODE> in Perl, you go though this buffering. <CODE>syswrite()</CODE> circumvents stdio and buffering.<P>In most stdio implementations, the type of buffering and the size of thebuffer varies according to the type of device. Disk files are blockbuffered, often with a buffer size of more than 2k. Pipes and sockets areoften buffered with a buffer size between 1/2 and 2k. Serial devices (e.g.modems, terminals) are normally line-buffered, and stdio sends the entireline when it gets the newline.<P>Perl does not support truly unbuffered output (except insofar as you can<CODE>syswrite(OUT, $char, 1)</CODE>). What it does instead support is ``command buffering'', in which aphysical write is performed after every output command. This isn't as hardon your system as unbuffering, but does get the output where you want itwhen you want it.<P>If you expect characters to get to your device when you print them there,you'll want to autoflush its handle, as in the older:<P><PRE>    use FileHandle;    open(DEV, &quot;&lt;+/dev/tty&quot;);      # ceci n'est pas une pipe    DEV-&gt;autoflush(1);</PRE><P>or the newer <FONT SIZE=-1>IO::*</FONT> modules:<P><PRE>    use IO::Handle;    open(DEV, &quot;&gt;/dev/printer&quot;);   # but is this?    DEV-&gt;autoflush(1);</PRE><P>or even this:<P><PRE>    use IO::Socket;               # this one is kinda a pipe?    $sock = IO::Socket::INET-&gt;new(PeerAddr =&gt; 'www.perl.com',                                  PeerPort =&gt; 'http(80)',                                  Proto    =&gt; 'tcp');    die &quot;$!&quot; unless $sock;</PRE><P><PRE>    $sock-&gt;autoflush();    $sock-&gt;print(&quot;GET /\015\012&quot;);    $document = join('', $sock-&gt;getlines());    print &quot;DOC IS: $document\n&quot;;</PRE><P>Note the hardcoded carriage return and newline in their octal equivalents. This is the <FONT SIZE=-1>ONLY</FONT> way (currently) to assure a proper flush on all platforms, including Macintosh.<P>You can use <CODE>select()</CODE> and the <CODE>$|</CODE> variable to control autoflushing (see <A HREF="../../tppmsgs/msgs1.htm#107" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlvar.html_">$|</A> and <A HREF="../../tppmsgs/msgs0.htm#68" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlfunc.html#select">select</A>):<P><PRE>    $oldh = select(DEV);    $| = 1;    select($oldh);</PRE><P>You'll also see code that does this without a temporary variable, as in<P><PRE>    select((select(DEV), $| = 1)[0]);</PRE><P><P><HR><H3><A NAME="How_do_I_change_one_line_in_a_fi">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?</A></H3>Although humans have an easy time thinking of a text file as being asequence of lines that operates much like a stack of playing cards -- orpunch cards -- computers usually see the text file as a sequence of bytes.In general, there's no direct way for Perl to seek to a particular line ofa file, insert text into a file, or remove text from a file.<P>(There are exceptions in special circumstances. Replacing a sequence ofbytes with another sequence of the same length is one. Another is using the <CODE>$DB_RECNO</CODE> array bindings as documented in <A HREF="../../tppmsgs/msgs1.htm#108" tppabs="http://www.perl.org/CPAN/doc/manual/html/lib/DB_File.html">the DB_File manpage</A>. Yet another is manipulating files with all lines the same length.)<P>The general solution is to create a temporary copy of the text file withthe changes you want, then copy that over the original.<P><PRE>    $old = $file;    $new = &quot;$file.tmp.$$&quot;;    $bak = &quot;$file.bak&quot;;</PRE><P><PRE>    open(OLD, &quot;&lt; $old&quot;)         or die &quot;can't open $old: $!&quot;;    open(NEW, &quot;&gt; $new&quot;)         or die &quot;can't open $new: $!&quot;;</PRE><P><PRE>    # Correct typos, preserving case    while (&lt;OLD&gt;) {        s/\b(p)earl\b/${1}erl/i;        (print NEW $_)          or die &quot;can't write to $new: $!&quot;;    }</PRE><P><PRE>    close(OLD)                  or die &quot;can't close $old: $!&quot;;    close(NEW)                  or die &quot;can't close $new: $!&quot;;</PRE><P><PRE>    rename($old, $bak)          or die &quot;can't rename $old to $bak: $!&quot;;    rename($new, $old)          or die &quot;can't rename $new to $old: $!&quot;;</PRE><P>Perl can do this sort of thing for you automatically with the <CODE>-i</CODE>command-line switch or the closely-related <CODE>$^I</CODE> variable (see<A HREF="../../tppmsgs/msgs0.htm#87" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlrun.html">the perlrun manpage</A> for more details). Note that<CODE>-i</CODE> may require a suffix on some non-Unix systems; see the platform-specificdocumentation that came with your port.<P><PRE>    # Renumber a series of tests from the command line    perl -pi -e 's/(^\s+test\s+)\d+/ $1 . ++$count /e' t/op/taint.t</PRE><P><PRE>    # form a script    local($^I, @ARGV) = ('.bak', glob(&quot;*.c&quot;));    while (&lt;&gt;) {        if ($. == 1) {            print &quot;This line should appear at the top of each file\n&quot;;        }        s/\b(p)earl\b/${1}erl/i;        # Correct typos, preserving case        print;        close ARGV if eof;              # Reset $.    }</PRE><P>If you need to seek to an arbitrary line of a file that changesinfrequently, you could build up an index of byte positions of where theline ends are in the file. If the file is large, an index of every tenth orhundredth line end would allow you to seek and read fairly efficiently. Ifthe file is sorted, try the look.pl library (part of the standard perldistribution).<P>In the unique case of deleting lines at the end of a file, you can use<CODE>tell()</CODE> and <CODE>truncate().</CODE> The following code snippetdeletes the last line of a file without making a copy or reading the wholefile into memory:<P><PRE>        open (FH, &quot;+&lt; $file&quot;);        while ( &lt;FH&gt; ) { $addr = tell(FH) unless eof(FH) }        truncate(FH, $addr);</PRE><P>Error checking is left as an exercise for the reader.<P><P><HR><H3><A NAME="How_do_I_count_the_number_of_lin">How do I count the number of lines in a file?</A></H3>One fairly efficient way is to count newlines in the file. The followingprogram uses a feature of tr///, as documented in <A HREF="../../tppmsgs/msgs0.htm#69" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlop.html">the perlop manpage</A>. If your text file doesn't end with a newline, then it's not really aproper text file, so this may report one fewer line than you expect.<P><PRE>    $lines = 0;    open(FILE, $filename) or die &quot;Can't open `$filename': $!&quot;;    while (sysread FILE, $buffer, 4096) {        $lines += ($buffer =~ tr/\n//);    }    close FILE;</PRE><P><P><HR><H3><A NAME="How_do_I_make_a_temporary_file_n">How do I make a temporary file name?</A></H3>Use the process <FONT SIZE=-1>ID</FONT> and/or the current time-value. If you need to havemany temporary files in one process, use a counter:<P><PRE>    BEGIN {        use IO::File;        use Fcntl;        my $temp_dir = -d '/tmp' ? '/tmp' : $ENV{TMP} || $ENV{TEMP};        my $base_name = sprintf(&quot;%s/%d-%d-0000&quot;, $temp_dir, $$, time());        sub temp_file {            my $fh = undef;            my $count = 0;            until (defined($fh) || $count &gt; 100) {                $base_name =~ s/-(\d+)$/&quot;-&quot; . (1 + $1)/e;                $fh = IO::File-&gt;new($base_name, O_WRONLY|O_EXCL|O_CREAT, 0644)            }            if (defined($fh)) {                return ($fh, $base_name);            } else {                return ();            }        }    }</PRE><P>Or you could simply use IO::Handle::new_tmpfile.<P><P><HR><H3><A NAME="How_can_I_manipulate_fixed_recor">How can I manipulate fixed-record-length files?</A></H3>The most efficient way is using <CODE>pack()</CODE> and<CODE>unpack().</CODE> This is faster than using <CODE>substr().</CODE>Here is a sample chunk of code to break up and put back together again somefixed-format input lines, in this case from the output of a normal,Berkeley-style ps:<P><PRE>    # sample input line:    #   15158 p5  T      0:00 perl /home/tchrist/scripts/now-what    $PS_T = 'A6 A4 A7 A5 A*';    open(PS, &quot;ps|&quot;);    $_ = &lt;PS&gt;; print;    while (&lt;PS&gt;) {        ($pid, $tt, $stat, $time, $command) = unpack($PS_T, $_);        for $var (qw!pid tt stat time command!) {            print &quot;$var: &lt;$$var&gt;\n&quot;;        }        print 'line=', pack($PS_T, $pid, $tt, $stat, $time, $command),                &quot;\n&quot;;    }</PRE><P><P><HR><H3><A NAME="How_can_I_make_a_filehandle_loca">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?</A></H3>You may have some success with typeglobs, as we always had to use in daysof old:<P><PRE>    local(*FH);</PRE><P>But while still supported, that isn't the best to go about getting localfilehandles. Typeglobs have their drawbacks. You may well want to use the <CODE>FileHandle</CODE> module, which creates new filehandles for you (see <A HREF="../../tppmsgs/msgs1.htm#109" tppabs="http://www.perl.org/CPAN/doc/manual/html/lib/FileHandle.html">the FileHandle manpage</A>):<P><PRE>    use FileHandle;    sub findme {        my $fh = FileHandle-&gt;new();        open($fh, &quot;&lt;/etc/hosts&quot;) or die &quot;no /etc/hosts: $!&quot;;        while (&lt;$fh&gt;) {            print if /\b127\.(0\.0\.)?1\b/;        }        # $fh automatically closes/disappears here    }</PRE><P>Internally, Perl believes filehandles to be of class IO::Handle. You mayuse that module directly if you'd like (see <A HREF="../../tppmsgs/msgs1.htm#110" tppabs="http://www.perl.org/CPAN/doc/manual/html/lib/IO/Handle.html">Handle</A>), or one of its more specific derived classes.<P>Once you have IO::File or FileHandle objects, you can pass them betweensubroutines or store them in hashes as you would any other scalar values:<P><PRE>    use FileHandle;</PRE><P><PRE>    # Storing filehandles in a hash and array    foreach $filename (@names) {        my $fh = new FileHandle($filename)              or die;        $file{$filename} = $fh;        push(@files, $fh);    }</PRE><P><PRE>    # Using the filehandles in the array    foreach $file (@files) {        print $file &quot;Testing\n&quot;;    }</PRE><P><PRE>    # You have to do the { } ugliness when you're specifying the    # filehandle by anything other than a simple scalar variable.    print { $files[2] } &quot;Testing\n&quot;;</PRE><P><PRE>    # Passing filehandles to subroutines    sub debug {        my $filehandle = shift;        printf $filehandle &quot;DEBUG: &quot;, @_;    }</PRE><P><PRE>    debug($fh, &quot;Testing\n&quot;);</PRE><P><P><HR><H3><A NAME="How_can_I_set_up_a_footer_format">How can I set up a footer format to be used with write()?</A></H3>There's no builtin way to do this, but <A HREF="../../tppmsgs/msgs1.htm#111" tppabs="http://www.perl.org/CPAN/doc/manual/html/pod/perlform.html">the perlform manpage</A> has a couple of techniques to make it possible for the intrepid hacker.

⌨️ 快捷键说明

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