This one's a killer: you have an if that prints out a warning about an uninitialized values... but when you print out all the variables in the if's condition, they are all anything but undefined: Consider the following:

#! /usr/local/bin/perl -w # 1 # 2 use strict; # 3 # 4 my $foo = shift || 'ok'; # 5 my $bar; # = undef # 6 # 7 print "foo contains [$foo]\n"; # 8 if( $foo eq 'nok' ) { # 9 print "foo is nok\n"; # 10 } # 11 elsif( $bar eq 'rat' ) { # 12 print "bar is rat\n"; # 13 } # 14 else { # 15 print "nothing\n"; # 16 } # 17
When run, this produces:
foo contains [ok] Use of uninitialized value in string eq at ifbug line 9. nothing

This rather mind-boggling error (a variable with a defined value is undefined) is an error of a different kind. Yes, there's an unitialised variable, but it's not on line 9 as the error message would have you believe. It's actually on line 12.

perl is complaining about $bar being undefined, but is getting its line numbers mixed up. Version 5.005_03 doesn't exhibit this behaviour, but 5.6 and 5.8 do. Which is yet another reason why I nearly lost my mind when I first encountered this problem.

Moral: if you have a unexplainable error on a line containing an if, look at its elsifs and else, you just never know.


just for the record, the above program was reformatted with perl -nle 'printf "%-30s # $.\n", $_'.

update: sigh. This is what Liz is talking about. I started composing the answer and then Real Life intervened. Oh well.

update 2: resigh. What a lunatic. I read this node, and then went and read About variable names, thought about what a hassle v-strings were, reminisced about pseudohashes... and forgot about the original gotcha expressed in this thread, which of course is exactly the same thing I just talked about. Oh well, I'll let it stand, but I feel like a right eejit.

Here, then, is a minor gotcha that gets me from time to time. I'm a bit of an awk fan. If you can express something in awk, it's always more concise than Perl. But sometimes you want to do something trickier, so you recast it in Perl using the -a autosplit switch: as an example, print out the uids of all logins that start with 'p':

awk -F: 'substr($1,0,1)=="p" {print $3}' /etc/passwd perl -F: -lane 'substr($F[0],0,1)eq"p" and print $F[2]' /etc/passwd

Nine times out of ten, I forget to substract one from the awk variables to produce the @F offsets, and then wonder why my script doesn't work. But if you're not an awker, it's hardly likely to catch you.

Apart from that, I can't think of any other gotchas :)


In reply to Re: Perl Gotchas. (if( condition) { bug }) by grinder
in thread Perl Gotchas. by EvdB

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.