home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.perl,news.answers
- Path: senator-bedfellow.mit.edu!bloom-beacon.mit.edu!spool.mu.edu!howland.reston.ans.net!pipex!uunet!boulder!wraeththu.cs.colorado.edu!tchrist
- From: Tom Christiansen <tchrist@cs.Colorado.EDU>
- Subject: Perl Frequently Asked Questions, part 4 of 4
- Message-ID: <CE9Brq.29B@Colorado.EDU>
- Followup-To: comp.lang.perl
- Originator: tchrist@wraeththu.cs.colorado.edu
- Sender: news@Colorado.EDU (USENET News System)
- Organization: University of Colorado at Boulder
- Date: Sat, 2 Oct 1993 06:38:13 GMT
- Approved: news-answers-request@MIT.Edu
- Expires: Wed, 1 Dec 1993 12:00:00 GMT
- Lines: 373
- Xref: senator-bedfellow.mit.edu comp.lang.perl:20585 news.answers:13123
-
- Archive-name: perl-faq/part4
- Version: $Id: perl-tech2,v 1.1 93/10/02 00:27:03 tchrist Exp Locker: tchrist $
-
- This posting contains answers to the following technical questions
- regarding Perl:
-
- 2.29) Why can't my perl program read from STDIN after I gave it ^D (EOF) ?
- 2.30) Do I always/never have to quote my strings or use semicolons?
- 2.31) How can I translate tildes in a filename?
- 2.32) How can I convert my shell script to Perl?
- 2.33) What is variable suicide and how can I prevent it?
- 2.34) Can I use Perl regular expressions to match balanced text?
- 2.35) Can I use Perl to run a telnet or ftp session?
- 2.36) What does "Malformed command links" mean?
- 2.37) How can I set up a footer format to be used with write()?
- 2.38) Why does my Perl program keep growing in size?
- 2.39) Can I do RPC in Perl?
- 2.40) What's the difference between delete and undef with %tables?
- 2.41) How do I do a "tail -f" in Perl?
-
-
- 2.29) Why can't my perl program read from STDIN after I gave it ^D (EOF) ?
-
- Because some stdio's set error and eof flags that need clearing.
-
- Try keeping around the seekpointer and go there, like this:
- $where = tell(LOG);
- seek(LOG, $where, 0);
-
- If that doesn't work, try seeking to a different part of the file and
- then back. If that doesn't work, try seeking to a different part of
- the file, reading something, and then seeking back. If that doesn't
- work, give up on your stdio package and use sysread. You can't call
- stdio's clearerr() from Perl, so if you get EINTR from a signal
- handler, you're out of luck. Best to just use sysread() from the
- start for the tty.
-
-
- 2.30) Do I always/never have to quote my strings or use semicolons?
-
- You don't have to quote strings that can't mean anything else
- in the language, like identifiers with any upper-case letters
- in them. Therefore, it's fine to do this:
-
- $SIG{INT} = Timeout_Routine;
- or
-
- @Days = (Sun, Mon, Tue, Wed, Thu, Fri, Sat, Sun);
-
- but you can't get away with this:
-
- $foo{while} = until;
-
- in place of
-
- $foo{'while'} = 'until';
-
- The requirements on semicolons have been increasingly relaxed. You no
- longer need one at the end of a block, but stylistically, you're
- better to use them if you don't put the curly brace on the same line:
-
- for (1..10) { print }
-
- is ok, as is
-
- @nlist = sort { $a <=> $b } @olist;
-
- but you probably shouldn't do this:
-
- for ($i = 0; $i < @a; $i++) {
- print "i is $i\n" # <-- oops!
- }
-
- because you might want to add lines later, and anyway,
- it looks funny. :-)
-
-
- 2.31) How can I translate tildes in a filename?
-
- Perl doesn't expand tildes -- the shell (ok, some shells) do.
- The classic request is to be able to do something like:
-
- open(FILE, "~/dir1/file1");
- open(FILE, "~tchrist/dir1/file1");
-
- which doesn't work. (And you don't know it, because you
- did a system call without an "|| die" clause! :-)
-
- If you *know* you're on a system with the csh, and you *know*
- that Larry hasn't internalized file globbing, then you could
- get away with
-
- $filename = <~tchrist/dir1/file1>;
-
- but that's pretty iffy.
-
- A better way is to do the translation yourself, as in:
-
- $filename =~ s#^~(\w+)(/.*)?$#(getpwnam($1))[7].$2#e;
-
- More robust and efficient versions that checked for error conditions,
- handed simple ~/blah notation, and cached lookups are all reasonable
- enhancements.
-
-
- 2.32) How can I convert my shell script to Perl?
-
- Larry's standard answer for this is to send your script to me (Tom
- Christiansen) with appropriate supplications and offerings. :-(
- That's because there's no automatic machine translator. Even if you
- were, you wouldn't gain a lot, as most of the external programs would
- still get called. It's the same problem as blind translation into C:
- you're still apt to be bogged down by exec()s. You have to analyze
- the dataflow and algorithm and rethink it for optimal speedup. It's
- not uncommon to see one, two, or even three orders of magnitude of
- speed difference between the brute-force and the recoded approaches.
-
-
- 2.33) What is variable suicide and how can I prevent it?
-
- Variable suicide is a nasty sideeffect of dynamic scoping and
- the way variables are passed by reference. If you say
-
- $x = 17;
- &munge($x);
- sub munge {
- local($x);
- local($myvar) = $_[0];
- ...
- }
-
- Then you have just clubbered $_[0]! Why this is occurring
- is pretty heavy wizardry: the reference to $x stored in
- $_[0] was temporarily occluded by the previous local($x)
- statement (which, you're recall, occurs at run-time, not
- compile-time). The work around is simple, however: declare
- your formal parameters first:
-
- sub munge {
- local($myvar) = $_[0];
- local($x);
- ...
- }
-
- That doesn't help you if you're going to be trying to access
- @_ directly after the local()s. In this case, careful use
- of the package facility is your only recourse.
-
- Another manifestation of this problem occurs due to the
- magical nature of the index variable in a foreach() loop.
-
- @num = 0 .. 4;
- print "num begin @num\n";
- foreach $m (@num) { &ug }
- print "num finish @num\n";
- sub ug {
- local($m) = 42;
- print "m=$m $num[0],$num[1],$num[2],$num[3]\n";
- }
-
- Which prints out the mysterious:
-
- num begin 0 1 2 3 4
- m=42 42,1,2,3
- m=42 0,42,2,3
- m=42 0,1,42,3
- m=42 0,1,2,42
- m=42 0,1,2,3
- num finish 0 1 2 3 4
-
- What's happening here is that $m is an alias for each
- element of @num. Inside &ug, you temporarily change
- $m. Well, that means that you've also temporarily
- changed whatever $m is an alias to!! The only workaround
- is to be careful with global variables, using packages,
- and/or just be aware of this potential in foreach() loops.
-
- The perl5 static autos via "my" will not have this problem.
-
-
- 2.34) Can I use Perl regular expressions to match balanced text?
-
- No, or at least, not by the themselves.
-
- Regexps just aren't powerful enough. Although Perl's patterns aren't
- strictly regular because they do backtracking (the \1 notation), you
- still can't do it. You need to employ auxiliary logic. A simple
- approach would involve keeping a bit of state around, something
- vaguely like this (although we don't handle patterns on the same line):
-
- while(<>) {
- if (/pat1/) {
- if ($inpat++ > 0) { warn "already saw pat1" }
- redo;
- }
- if (/pat2/) {
- if (--$inpat < 0) { warn "never saw pat1" }
- redo;
- }
- }
-
- A rather more elaborate subroutine to pull out balanced and possibly
- nested single chars, like ` and ', { and }, or ( and ) can be found
- on convex.com in /pub/perl/scripts/pull_quotes.
-
-
- 2.35) Can I use Perl to run a telnet or ftp session?
-
- Sure, you can connect directly to them using sockets, or you can run a
- session on a pty. In either case, Randal's chat2 package, which is
- distributed with the perl source, will come in handly. It address
- much the same problem space as Don Libes's expect package does. Two
- examples of using managing an ftp session using chat2 can be found on
- convex.com in /pub/perl/scripts/ftp-chat2.shar .
-
- Caveat lector: chat2 is documented only by example, may not run on
- System V systems, and is subtly machine dependent both in its ideas
- of networking and in pseudottys.
-
-
- 2.36) What does "Malformed command links" mean?
-
- This is a bug in 4.035. While in general it's merely a cosmetic
- problem, it often comanifests with a highly undesirable coredumping
- problem. Programs known to be affected by the fatal coredump include
- plum and pcops. Since perl5 is pretty much a total rewrite, we can
- count on it being fixed then, but if anyone tracks down the coredump
- problem before then, a significant portion of the Perl world would
- rejoice.
-
-
- 2.37) How can I set up a footer format to be used with write()?
-
- While the $^ variable contains the name of the current header format,
- there is no corresponding mechanism to automatically do the same thing
- for a footer. Not knowing how big a format is going to be until you
- evaluate it is one of the major problems.
-
- If you have a fixed-size footer, you can get footers by checking for
- line left on page ($-) before each write, and printing the footer
- yourself if necessary.
-
- Another strategy is to open a pipe to yourself, using open(KID, "|-")
- and always write()ing to the KID, who then postprocesses its STDIN to
- rearrange headers and footers however you like. Not very convenient,
- but doable.
-
-
- 2.38) Why does my Perl program keep growing in size?
-
- While there may be a real memory leak in the Perl source code or even
- whichever malloc() you're using, common causes are incomplete eval()s
- or local()s in loops.
-
- An eval() which terminates in error due to a failed parsing
- will leave a bit of memory unusable.
-
- A local() inside a loop:
-
- for (1..100) {
- local(@array);
- }
-
- will build up 100 versions of @array before the loop is done.
- The work-around is:
-
- local(@array);
- for (1..100) {
- undef @array;
- }
-
- Larry reports that this behavior is fixed for perl5.
-
-
- 2.39) Can I do RPC in Perl?
-
- Yes, you can, since Perl has access to sockets. An example of the rup
- program written in Perl can be found in the script ruptime.pl at
- the scripts archive on coombs.anu.edu.au . I warn you, however,
- that it's not a pretty site, as it's used nothing from h2ph or c2ph,
- so everything is utterly hard-wired.
-
-
- 2.40) What's the difference between delete and undef with %tables?
-
- Pictures help... here's the %ary table:
-
- keys values
- +------+------+
- | a | 3 |
- | x | 7 |
- | d | 0 |
- | e | 2 |
- +------+------+
-
- And these conditions hold
-
- $ary{'a'} is true
- $ary{'d'} is false
- defined $ary{'d'} is true
- defined $ary{'a'} is true
- grep ($_ eq 'a', keys %ary) is true
-
- If you now say
-
- undef $ary{'a'}
-
- your table now reads:
-
-
- keys values
- +------+------+
- | a | undef|
- | x | 7 |
- | d | 0 |
- | e | 2 |
- +------+------+
-
- and these conditions now hold; changes in caps:
-
- $ary{'a'} is FALSE
- $ary{'d'} is false
- defined $ary{'d'} is true
- defined $ary{'a'} is FALSE
- grep ($_ eq 'a', keys %ary) is true
-
- Notise the last two: you have an undef value, but a defined key!
-
- Now, consider this:
-
- delete $ary{'a'}
-
- your table now reads:
-
- keys values
- +------+------+
- | x | 7 |
- | d | 0 |
- | e | 2 |
- +------+------+
-
- and these conditions now hold; changes in caps:
-
- $ary{'a'} is false
- $ary{'d'} is false
- defined $ary{'d'} is true
- defined $ary{'a'} is false
- grep ($_ eq 'a', keys %ary) is FALSE
-
- See, the whole entry is gone!
-
- 2.41) How do I do a "tail -f" in Perl?
-
- Larry says that the solution is to put a call to seek in yourself.
- First try
-
- seek(GWFILE, 0, 1);
-
- If that doesn't work (depends on 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);
- }
- --
- Tom Christiansen tchrist@cs.colorado.edu
- Consultant
- Boulder Colorado 303-444-3212
-