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

📄 perlfaq5.pod

📁 MSYS在windows下模拟了一个类unix的终端
💻 POD
📖 第 1 页 / 共 3 页
字号:
    # make STDOUT go to three files, plus original STDOUT    open (STDOUT, "| tee file1 file2 file3") or die "Teeing off: $!\n";    print "whatever\n"                       or die "Writing: $!\n";    close(STDOUT)                            or die "Closing: $!\n";Otherwise you'll have to write your own multiplexing printfunction--or your own tee program--or use Tom Christiansen's,at http://www.perl.com/CPAN/authors/id/TOMC/scripts/tct.gz , which iswritten in Perl and offers much greater functionalitythan the stock version.=head2 How can I read in an entire file all at once?The customary Perl approach for processing all the lines in a file is todo so one line at a time:    open (INPUT, $file) 	|| die "can't open $file: $!";    while (<INPUT>) {	chomp;	# do something with $_    }     close(INPUT)	    	|| die "can't close $file: $!";This is tremendously more efficient than reading the entire file intomemory as an array of lines and then processing it one element at a time,which is often--if not almost always--the wrong approach.  Wheneveryou see someone do this:    @lines = <INPUT>;you should think long and hard about why you need everything loadedat once.  It's just not a scalable solution.  You might also find itmore 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 elementthe array actually accesses the corresponding line in the file.On very rare occasion, you may have an algorithm that demands thatthe entire file be in memory at once as one scalar.  The simplest solutionto 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:    @lines = `cat $file`;This tiny but expedient solution is neat, clean, and portable toall systems on which decent tools have been installed.  For thosewho prefer not to use the toolbox, you can of course read the filemanually, although this makes for more complicated code.    {	local(*INPUT, $/);	open (INPUT, $file) 	|| die "can't open $file: $!";	$var = <INPUT>;    }That temporarily undefs your record separator, and will automatically close the file at block exit.  If the file is already open, just use this:    $var = do { local $/; <INPUT> };=head2 How can I read in a file by paragraphs?Use the C<$/> variable (see L<perlvar> for details).  You can eitherset it to C<""> to eliminate empty paragraphs (C<"abc\n\n\n\ndef">,for instance, gets treated as two paragraphs and not three), orC<"\n\n"> to accept empty paragraphs.Note that a blank line must have no blanks in it.  Thus C<"fred\n\nstuff\n\n"> is one paragraph, but C<"fred\n\nstuff\n\n"> is two.=head2 How can I read a single character from a file?  From the keyboard?You can use the builtin C<getc()> function for most filehandles, butit won't (easily) work on a terminal device.  For STDIN, either usethe Term::ReadKey module from CPAN or use the sample code inL<perlfunc/getc>.If your system supports the portable operating system programminginterface (POSIX), you can use the following code, which you'll noteturns off echo processing as well.    #!/usr/bin/perl -w    use strict;    $| = 1;    for (1..4) {	my $got;	print "gimme: ";	$got = getone();	print "--> $got\n";    }    exit;    BEGIN {	use POSIX qw(:termios_h);	my ($term, $oterm, $echo, $noecho, $fd_stdin);	$fd_stdin = fileno(STDIN);	$term     = POSIX::Termios->new();	$term->getattr($fd_stdin);	$oterm     = $term->getlflag();	$echo     = ECHO | ECHOK | ICANON;	$noecho   = $oterm & ~$echo;	sub cbreak {	    $term->setlflag($noecho);	    $term->setcc(VTIME, 1);	    $term->setattr($fd_stdin, TCSANOW);	}	sub cooked {	    $term->setlflag($oterm);	    $term->setcc(VTIME, 0);	    $term->setattr($fd_stdin, TCSANOW);	}	sub getone {	    my $key = '';	    cbreak();	    sysread(STDIN, $key, 1);	    cooked();	    return $key;	}    }    END { cooked() }The Term::ReadKey module from CPAN may be easier to use.  Recent versionsinclude also support for non-portable systems as well.    use Term::ReadKey;    open(TTY, "</dev/tty");    print "Gimme a char: ";    ReadMode "raw";    $key = ReadKey 0, *TTY;    ReadMode "normal";    printf "\nYou said %s, char number %03d\n",        $key, ord $key;For legacy DOS systems, Dan Carson <dbc@tc.fluke.COM> reports the following:To put the PC in "raw" mode, use ioctl with some magic numbers gleanedfrom msdos.c (Perl source file) and Ralf Brown's interrupt list (comesacross the net every so often):    $old_ioctl = ioctl(STDIN,0,0);     # Gets device info    $old_ioctl &= 0xff;    ioctl(STDIN,1,$old_ioctl | 32);    # Writes it back, setting bit 5Then to read a single character:    sysread(STDIN,$c,1);               # Read a single characterAnd to put the PC back to "cooked" mode:    ioctl(STDIN,1,$old_ioctl);         # Sets it back to cooked mode.So now you have $c.  If C<ord($c) == 0>, you have a two byte code, whichmeans you hit a special key.  Read another byte with C<sysread(STDIN,$c,1)>,and that value tells you what combination it was according to thistable:    # PC 2-byte keycodes = ^@ + the following:    # HEX     KEYS    # ---     ----    # 0F      SHF TAB    # 10-19   ALT QWERTYUIOP    # 1E-26   ALT ASDFGHJKL    # 2C-32   ALT ZXCVBNM    # 3B-44   F1-F10    # 47-49   HOME,UP,PgUp    # 4B      LEFT    # 4D      RIGHT    # 4F-53   END,DOWN,PgDn,Ins,Del    # 54-5D   SHF F1-F10    # 5E-67   CTR F1-F10    # 68-71   ALT F1-F10    # 73-77   CTR LEFT,RIGHT,END,PgDn,HOME    # 78-83   ALT 1234567890-=    # 84      CTR PgUpThis is all trial and error I did a long time ago; I hope I'm reading thefile that worked...=head2 How can I tell whether there's a character waiting on a filehandle?The very first thing you should do is look into getting the Term::ReadKeyextension from CPAN.  As we mentioned earlier, it now even has limitedsupport for non-portable (read: not open systems, closed, proprietary,not POSIX, not Unix, etc) systems.You should also check out the Frequently Asked Questions list incomp.unix.* for things like this: the answer is essentially the same.It's very system dependent.  Here's one solution that works on BSDsystems:    sub key_ready {	my($rin, $nfd);	vec($rin, fileno(STDIN), 1) = 1;	return $nfd = select($rin,undef,undef,0);    }If you want to find out how many characters are waiting, there'salso the FIONREAD ioctl call to be looked at.  The I<h2ph> tool thatcomes with Perl tries to convert C include files to Perl code, whichcan be C<require>d.  FIONREAD ends up defined as a function in theI<sys/ioctl.ph> file:    require 'sys/ioctl.ph';    $size = pack("L", 0);    ioctl(FH, FIONREAD(), $size)    or die "Couldn't call ioctl: $!\n";    $size = unpack("L", $size);If I<h2ph> wasn't installed or doesn't work for you, you canI<grep> the include files by hand:    % grep FIONREAD /usr/include/*/*    /usr/include/asm/ioctls.h:#define FIONREAD      0x541BOr write a small C program using the editor of champions:    % cat > fionread.c    #include <sys/ioctl.h>    main() {        printf("%#08x\n", FIONREAD);    }    ^D    % cc -o fionread fionread.c    % ./fionread    0x4004667fAnd then hard-code it, leaving porting as an exercise to your successor.    $FIONREAD = 0x4004667f;         # XXX: opsys dependent    $size = pack("L", 0);    ioctl(FH, $FIONREAD, $size)     or die "Couldn't call ioctl: $!\n";    $size = unpack("L", $size);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?First try    seek(GWFILE, 0, 1);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 thenext <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:	for (;;) {	  for ($curpos = tell(GWFILE); <GWFILE>; $curpos = tell(GWFILE)) {	    # search for some stuff and put it into files	  }	  # sleep for a while	  seek(GWFILE, $curpos, 0);  # seek to where we had been	}If this still doesn't work, look into the POSIX module.  POSIX definesthe clearerr() method, which can remove the end of file condition on afilehandle.  The method: read until end of file, clearerr(), read somemore.  Lather, rinse, repeat.There's also a File::Tail module from CPAN.=head2 How do I dup() a filehandle in Perl?If you check L<perlfunc/open>, you'll see that several of the waysto call open() should do the trick.  For example:    open(LOG, ">>/tmp/logfile");    open(STDERR, ">&LOG");Or even with a literal numeric descriptor:   $fd = $ENV{MHCONTEXTFD};   open(MHCONTEXT, "<&=$fd");	# like fdopen(3S)Note that "<&STDIN" makes a copy, but "<&=STDIN" makean alias.  That means if you close an aliased handle, allaliases become inaccessible.  This is not true with 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?This should rarely be necessary, as the Perl close() function is to beused for things that Perl opened itself, even if it was a dup of anumeric descriptor as with MHCONTEXT above.  But if you really haveto, 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():    { 	local *F; 	open F, "<&=$fd" or die "Cannot reopen fd=$fd: $!";	close F;    }=head2 Why can't I use "C:\temp\foo" in DOS paths?  What doesn't `C:\temp\foo.exe` work?Whoops!  You just put a tab and a formfeed into that filename!Remember that within double quoted strings ("like\this"), thebackslash is an escape character.  The full list of these is inL<perlop/Quote and Quote-like Operators>.  Unsurprisingly, you don'thave a file called "c:(tab)emp(formfeed)oo" or"c:(tab)emp(formfeed)oo.exe" on your legacy DOS filesystem.Either single-quote your strings, or (preferably) use forward slashes.Since all DOS and Windows versions since something like MS-DOS 2.0 or sohave treated C</> and C<\> the same in a path, you might as well use theone that doesn't clash with Perl--or the POSIX shell, ANSI C and C++,awk, Tcl, Java, or Python, just to mention a few.  POSIX pathsare more portable, too.=head2 Why doesn't glob("*.*") get all the files?Because even on non-Unix ports, Perl's glob function follows standardUnix globbing semantics.  You'll need C<glob("*")> to get all (non-hidden)files.  This makes glob() portable even to legacy systems.  Yourport may include proprietary globbing functions as well.  Check itsdocumentation for details.=head2 Why does Perl let me delete read-only files?  Why does C<-i> clobber protected files?  Isn't this a bug in Perl?This is elaborately and painstakingly described in the "Far More ThanYou Ever Wanted To Know" inhttp://www.perl.com/CPAN/doc/FMTEYEWTK/file-dir-perms .The executive summary: learn how your filesystem works.  Thepermissions on a file say what can happen to the data in that file.The permissions on a directory say what can happen to the list offiles in that directory.  If you delete a file, you're removing itsname from the directory (so the operation depends on the permissionsof the directory, not of the file).  If you try to write to the file,the permissions of the file govern whether you're allowed to.=head2 How do I select a random line from a file?Here's an algorithm from the Camel Book:    srand;    rand($.) < 1 && ($line = $_) while <>;This has a significant advantage in space over reading the wholefile in.  A simple proof by induction is available upon request if you doubt the algorithm's correctness.=head2 Why do I get weird spaces when I print an array of lines?Saying    print "@lines\n";joins together the elements of C<@lines> with a space between them.If C<@lines> were C<("little", "fluffy", "clouds")> then the abovestatement would print    little fluffy cloudsbut if each element of C<@lines> was a line of text, ending a newlinecharacter C<("little\n", "fluffy\n", "clouds\n")> then it would print:    little     fluffy     cloudsIf your array contains lines, just print them:    print @lines;=head1 AUTHOR AND COPYRIGHTCopyright (c) 1997-1999 Tom Christiansen and Nathan Torkington.All rights reserved.When included as an integrated part of the Standard Distributionof Perl or of its documentation (printed or otherwise), this works iscovered under Perl's Artistic License.  For separate distributions ofall or part of this FAQ outside of that, see L<perlfaq>.Irrespective of its distribution, all code examples here are in the publicdomain.  You are permitted and encouraged to use this code and anyderivatives thereof in your own programs for fun or for profit as yousee fit.  A simple comment in the code giving credit to the FAQ wouldbe courteous but is not required.

⌨️ 快捷键说明

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