Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

How not to pass undef variables

by dru145 (Friar)
on Jan 10, 2002 at 21:48 UTC ( [id://137784]=perlquestion: print w/replies, xml ) Need Help??

dru145 has asked for the wisdom of the Perl Monks concerning the following question:

Fellow monks,

I'm having an issue that I can't seem to figure out. Below is my subroutine. It's purpose is to match an email address from a whois query and have a list of email addresses to ignore. The ignore regex seems to work fine, but when an email is ignored, Perl still appears to be assigning the value to undef because I'm getting this error when running the script:
Use of uninitialized value in split at ./temp.pl line 258. Use of uninitialized value in string at ./temp.pl line 290. Use of uninitialized value in concatenation (.) at ./temp.pl line 290. Can't use an undefined value as a symbol reference at /usr/lib/perl5/s +ite_perl/5.6.0/Mail/Sender.pm line 832.


It appears to be dying because Mail::Sender is being passed an undefined value. Any suggestions on how to code this properly? Also, does my ignore regex look ok?
sub match { my (@newemails, @emails); # Email addresses to ignore my $ignore = qr(([-.\w]+\@apnic\.[com|net]) | ([-.\w]+\@uu\.net) | ( +hostmaster\@nic\.or\.kr) | ([-.\w]+\@[RIPE\.NET|ripe\.net]) | ([-.\w]+\@iana\.org) | (NOC\@SPRINT\.NET); # Save all emails from whois query to an array @emails = $result =~ m/([-.\w]+\@[-.\w]+)/g; my %saw; @emails = grep(!$saw{$_}++, @emails); #remove duplicates # Remove all ignore emails and save to new array foreach (@emails){ next if $_ =~ $ignore; push(@newemails, $_); } #Save the email and domain portion to separate vars my ($email, $domain) = split(/\@/, $newemails[0]); #Run the mail sub for each email address &mail($newemails[0], $domain); } *Note: I know my regex will not match 100% of emails, but I'm happy wi +th 75 - 90%. It's been working out well so far.

Thanks,
Dru
Another satisfied monk.

Replies are listed 'Best First'.
Re: How not to pass undef variables
by count0 (Friar) on Jan 10, 2002 at 22:02 UTC
    From the very first assignment to @emails, you have no idea how many, if any, elements it has.

    A good general rule to follow is that when you don't know if there is a value, test it! ;)

    The @emails = grep... statement doesn't need any input, so you're safe there.
    The foreach... doesn't need @emails to have anything in it, so again, that's ok.

    When you get down to the split(), you have a problem. If @newemails has no elements in it.. perl will complain, and $email and $domain will be undefined.

    The simplest way to deal with this situation is to test if @newemails has any elements. Wrap any code that depends on it containing something, into that test:
    if (scalar @newemails) { my ($email, $domain) = split(/\@/, $newemails[0]); mail($newemails[0], $domain); }

(jeffa) Re: How not to pass undef variables
by jeffa (Bishop) on Jan 10, 2002 at 22:07 UTC
    I can't run this code to find the origin of the error, so instead i present you with some strategies for finding this bug.

    I would pull out the old Data::Dumper module and use it to find where that/those undef's are. You say that it happens duing the ignore code, if that's true, than the undef's where already in @emails. grep shouldn't return an undef (in your context), so i am guessing that the undef's are creeping in during the 'regex split' or from the split just before the call to &mail().

    Getting rid of the undef's is best done by not putting them in, but you can always bypass them like so:

    foreach (@emails){ next unless $_; next if $_ =~ $ignore; push(@newemails, $_); }

    Not the best way, that solution doesn't solve the problem, just the symptom. Use Data::Dumper on @emails once before you do anything with it, and once after your 'regex split', like so:

    print Dumper \@emails;

    The error could be in this line:

    my ($email, $domain) = split(/\@/, $newemails[0]);

    Print out the contents to see what is really there. This is one way (probablly not the best) to avoid calling &mail():

    &mail($newemails[0], $domain) if $newemails[0] and $domain;

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    F--F--F--F--F--F--F--F--
    (the triplet paradiddle)
    
Re: How not to pass undef variables
by danger (Priest) on Jan 10, 2002 at 22:12 UTC

    My guess would be that your @newmails array is empty either because the @emails array was empty or because everything is being ignored by your $ignore regex (which uses character classes in a few places where I'm pretty sure you just meant to use parens for grouping). Have you tried printing out the @newmails array after your foreach loop?

Re: How not to pass undef variables
by gav^ (Curate) on Jan 10, 2002 at 22:43 UTC
    There are some cunning modules that may help. I suggest:
    use Emails::Find; find_emails($result, \&callback); sub callback { my $email = shift; return if $email->host eq 'uu.net'; return if $email->host =~ /apnic\.(?:com|net)/; return if $email->address eq 'NOC@SPRINT.NET'; # etc print $email->address, "\n"; }
    Hope this helps.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://137784]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (3)
As of 2024-04-25 05:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found