[comp.lang.perl] Novice surprise

bobg+@andrew.cmu.edu (Robert Steven Glickstein) (02/12/91)

Today I ran my very first Perl program; it was generated by a2p.  The
awk program was:

    BEGIN {x = 0}
    $0 == "" {x = 1}
    x == 1

The perl program produced was:

    eval '$'.$1.'$2;' while $ARGV[0] =~ /^([A-Za-z_]+=)(.*)/ && shift;
    			# process any FOO=bar switches

    $x = 0;

    while (<>) {
        chop;	# strip record separator
        if ($_ eq '') {
	    $x = 1;
        }
        print $_ if $x == 1;
    }

The idea:  skip the first lines of the input until a blank line is
found, then start echoing the lines.  The awk program worked fine, the
perl program did not.  I kept getting "cannot open file" errors.

It was two hours of staring at this stupid thing before I realized
that the problem was this:  The filenames that I was passing as
arguments happened to begin with a "+".  Since I didn't have
write-access, I got a "cannot open file" error.  I couldn't figure out
a way to circumvent this in Perl, so instead of the command-line

    perlscript +a +b +c

I used

    perlscript ./+a ./+b ./+c

The big question:  What is the *right* way around this problem?

______________                  _____________________________
Bob Glickstein                | Internet: bobg@andrew.cmu.edu
Information Technology Center | Bitnet:   bobg%andrew@cmuccvma.bitnet
Carnegie Mellon University    | UUCP:     ...!harvard!andrew.cmu.edu!bobg
Pittsburgh, PA  15213-3890    |
(412) 268-6743                | Sinners can repent, but stupid is forever

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (02/12/91)

In article <cbhl9z200VsnE1=K1b@andrew.cmu.edu> bobg+@andrew.cmu.edu (Robert Steven Glickstein) writes:
: It was two hours of staring at this stupid thing before I realized
: that the problem was this:  The filenames that I was passing as
: arguments happened to begin with a "+".  Since I didn't have
: write-access, I got a "cannot open file" error.  I couldn't figure out
: a way to circumvent this in Perl, so instead of the command-line
: 
:     perlscript +a +b +c
: 
: I used
: 
:     perlscript ./+a ./+b ./+c
: 
: The big question:  What is the *right* way around this problem?

Er, don't use a toy language for a real problem...  :-)

I think that most people avoid the problem by not using filenames beginning
with + or >.  If you really want to write a bulletproof script, you might
put the following before the initial loop:

for (@ARGV) { s#^([^/])#./$1#; s#$#\0#; }
while (<>) {...

In general, filenames starting with + aren't quite as dangerous as those
starting with -, but there are some programs that use + to introduce
switches, so it's probably a bad idea.  You can't, for example, say

    sort +a +b +c

Just don't create a file called -rf.  :-)

Larry

fuchs@tmipi4.telematik.informatik.uni-karlsruhe.de (Harald Fuchs) (02/12/91)

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) writes:

>I think that most people avoid the problem by not using filenames beginning
>with + or >.  If you really want to write a bulletproof script, you might
>put the following before the initial loop:

>for (@ARGV) { s#^([^/])#./$1#; s#$#\0#; }
>while (<>) {...

Shouldn't that be
  for (@ARGV) { s#^[^./]#./$&#; s#$#\0#; }
Note the period:     ^
--

Harald Fuchs <fuchs@tmipi4.telematik.informatik.uni-karlsruhe.de>
<fuchs@telematik.informatik.uni-karlsruhe.dbp.de>   *gulp*

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (02/12/91)

In article <fuchs.666322665@tmipi4> fuchs@tmipi4.telematik.informatik.uni-karlsruhe.de (Harald Fuchs) writes:
: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) writes:
: 
: >I think that most people avoid the problem by not using filenames beginning
: >with + or >.  If you really want to write a bulletproof script, you might
: >put the following before the initial loop:
: 
: >for (@ARGV) { s#^([^/])#./$1#; s#$#\0#; }
: >while (<>) {...
: 
: Shouldn't that be
:   for (@ARGV) { s#^[^./]#./$&#; s#$#\0#; }
: Note the period:     ^

You can if it makes you feel better, but it doesn't hurt (much) to add an
extra ./ on the front of any relative pathname (even those beginning with .
or ..).  The current directory will even be in the cache already, so there's
no extra disk access.

Larry

tneff@bfmny0.BFM.COM (Tom Neff) (02/12/91)

In article <11393@jpl-devvax.JPL.NASA.GOV> lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) writes:
>I think that most people avoid the problem by not using filenames beginning
>with + or >.  

It's not always up to us, is it!  Sometimes we need our Perl tools 
just to DEAL with the weird stuff other peoples' programs create.

>              If you really want to write a bulletproof script, you might
>put the following before the initial loop:
>
>for (@ARGV) { s#^([^/])#./$1#; s#$#\0#; }
>while (<>) {...

Nah, too complicated.  Just

	grep(ARGV,s//</);

tneff@bfmny0.BFM.COM (Tom Neff) (02/12/91)

In article <1991Feb12.165848.18718@convex.com> tchrist@convex.COM (Tom Christiansen) writes:
>From the keyboard of tneff@bfmny0.BFM.COM (Tom Neff):
>:	grep(ARGV,s//</);
>
>Hello?  Don't you mean
>
>	grep(s//</, @ARGV);
>
>It's kind of a pity perl doesn't flag this as an error.

Groooooaaannn!  :-(  --> :-)

I'll tell you what's really sick -- mine worked too!  Go figure.

tchrist@convex.COM (Tom Christiansen) (02/13/91)

From the keyboard of tneff@bfmny0.BFM.COM (Tom Neff):
:>[Larry said]
:>              If you really want to write a bulletproof script, you might
:>put the following before the initial loop:
:>
:>for (@ARGV) { s#^([^/])#./$1#; s#$#\0#; }
:>while (<>) {...
:
:Nah, too complicated.  Just
:
:	grep(ARGV,s//</);

Hello?  Don't you mean

	grep(s//</, @ARGV);

It's kind of a pity perl doesn't flag this as an error.

And I would use s/^/</ myself -- I always think // will 
be a remembered /pattern_match/, although in s/// it doesn't
seem to me.  Maybe it only counts for m// things.  Larry?

Also, Larry's works on things that Tom Neff's doesn't: you
can't open a file named "-" nor any with trailing white space
unless you use Larry's quotation mechanism, or it's functional
equivalent, like

    grep(s#^([^/])(.*)#./$1$2\0#, @ARGV);

--tom
--
 "All things are possible, but not all expedient."  (in life, UNIX, and perl)

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (02/13/91)

In article <22434654@bfmny0.BFM.COM> tneff@bfmny0.BFM.COM (Tom Neff) writes:
: Nah, too complicated.  Just
: 
: 	grep(ARGV,s//</);

Not complicated enough.  (Not to mention backwards.)  What if the filename
begins with &?  What if // invokes a previous pattern?  Try

	grep(s/.*/< $&\0/, @ARGV);

And that still doesn't handle leading whitespace.

By the way, /foo/ && s//bar/ is busted in 44, seemingly.  I'm looking at it.
/f../ && s//bar/ works right though.  Looks like the constant string optimizer
got me.

Larry

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (02/13/91)

In article <1991Feb12.165848.18718@convex.com> tchrist@convex.COM (Tom Christiansen) writes:
: Also, Larry's works on things that Tom Neff's doesn't: you
: can't open a file named "-" nor any with trailing white space
: unless you use Larry's quotation mechanism, or it's functional
: equivalent, like
: 
:     grep(s#^([^/])(.*)#./$1$2\0#, @ARGV);

Unfortunately, that's not a functional equivalent, since it won't put the
trailing null on an absolute pathname.

Larry