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 :) |