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

I have 5 name and 5 email fields named fname1, fname2, fname3 and so on and fmail1, fmail2, fmail3 and so on. Instead of breaking down and creating three 5 large email sections, I thought throwing it into a loop would make more sense.

For some reason, it's not liking me appending $cnt to the variables because it errors out with

Global symbol "$fmail" requires explicit package name at raf.pl line 9 +2. syntax error at raf.pl line 92, near "$fmail$cnt " Global symbol "$fmail" requires explicit package name at raf.pl line 9 +5. Global symbol "$fname" requires explicit package name at raf.pl line 9 +8.
Since $fmail doesn't exist and neither does $fname, the script fails. Does anyone know how I can fix this problem?
my $cnt = 0; for (1 .. 5) { $cnt++; if ($fmail$cnt ne "") { open(MAIL,"| $sendmail") or die "Can't open sendmail $!"; print MAIL "To: $fmail$cnt\n"; print MAIL "From: $email\n"; print MAIL "Subject: Refer A Friend\n"; print MAIL "Dear $fname$cnt,\n\n"; print MAIL "Your friend, $name at $email, visited out site re +cently and thought you would be interested..\n\n"; print MAIL "This is NOT spam. This email was sent by someone +who said they knew you. Your email address is not stored in any data +bases and will not be sold or given to anyone at any time. This is the only time you wil +l receive an email from us."; close(MAIL); } }

Replies are listed 'Best First'.
Re: $var$cnt problems
by castaway (Parson) on Jul 08, 2005 at 16:38 UTC
Re: $var$cnt problems
by monarch (Priest) on Jul 08, 2005 at 16:36 UTC
    Instead of saying $fmail$cnt try saying ${"fmail$cnt"}. This uses references, but not the kind that involves an address of memory. Instead you're referring to a variable by name.

    This kind of calling convention will break use strict however so it is something that I personally steer clear of.

    Another approach would be to create a hash and store your fields in there e.g.:

    my %fields = ( fname1 => 'John', fmail1 => 'john.lizmore@something.com', fname2 => 'Lisa', fmail2 => 'lisa.lizmore@something.com' );

    Update: thanks to Transient for pointing out an error in my variable name.

    Update2: merlyn says PLEASE do not suggest to people to use softrefs! I downvoted your node for that. How kind of merlyn to send me that message. I do want to point out that I believe merlyn did not read this article, as I also discourage the use of softrefs. As a result, to assist some of the skim-readers on this site, I have gone back and bolded the appropriate statement.

      Or just use two arrays, since the subscripts are numeric.
      $fname[0]='John'; $fmail[0]='john.lizmore@something.com'; $fname[1]='Lisa'; $fname[2]='lisa.lizmore@something.com';
      I do want to point out that I believe merlyn did not read this article, as I also discourage the use of softrefs. As a result, to assist some of the skim-readers on this site, I have gone back and bolded the appropriate statement.
      Correct. I read your first statement that says:
      Instead of saying $fmail$cnt try saying ${"fmail$cnt"}. This uses references, but not the kind that involves an address of memory. Instead you're referring to a variable by name.
      That uses softreferences. That's what I was downvoting you for. The fact that your statement had to be bolded later proves that it wasn't strong enough when I first skimmed it.

      Had you instead written as your first paragraph:

      There will be other posts in this thread that show you how to do this with soft references. Please ignore them. They are bad.
      You would have gotten an upvote instead of a downvote.

      Just something to note for the future. Do not suggest a broken solution, even if you "fix it" later in the same message.

      -- Randal L. Schwartz, Perl hacker
      Be sure to read my standard disclaimer if this is a reply.


      update:
      merlyn says PLEASE do not suggest to people to use softrefs! I downvoted your node for that.
      By the way, that was a private message to you, not a node. The fact that you took private communication and made it public is both (a) rude and (b) a copyright violation. Please don't do that again, and I won't have charges filed against you this time. {grin}
        You always have the option of not voting?

        I, personally, believe in understand what I am voting on.. arguably politics rarely works this way, but we are programmers so there's no reason for us not to understand what we are saying when we vote.

        I was not attempting to slander you, so I'm confused about the legal charges comment you made. I just wanted to point out the reason why I felt it necessary to bold face a portion of my short comment. You should feel proud that you gave me the inspiration to make judgements easier for those with short attention spans! I am only giving you credit, cheer up!

        The fact that you took private communication and made it public is both (a) rude and (b) a copyright violation. Please don't do that again, and I won't have charges filed against you this time.

        In order to pursue an action against the copyright infringement, you will have to register the copyright. (You may hold the copyright without registration, but it is unactionable until registered.) In this case, how will you register for the copyright in a manner that could support the case for infringement?

Re: $var$cnt problems
by davidrw (Prior) on Jul 08, 2005 at 16:37 UTC
    Can i assume this is a CGI script? How are you currently accessing any of the GET/POST'd variables? I think you're looking for something along the lines of:
    use strict; use warnings; use CGI qw/:standard/; my $name = ...; # param('name') maybe? my $email = ...; # param('email') maybe? foreach my $cnt ( 1.. 5 ){ my $fmail = param('fmail'.$cnt); my $fname = param('fname'.$cnt); next unless $fmail && $fname; open(MAIL,"| $sendmail") or die "Can't open sendmail $!"; print MAIL "To: $fmail\n"; print MAIL "From: $email\n"; print MAIL "Subject: Refer A Friend\n"; print MAIL "Dear $fname,\n\n"; print MAIL "Your friend, $name at $email, visited out site re +cently and thought you would be interested..\n\n"; print MAIL "This is NOT spam. This email was sent by someone +who said they knew you. Your email address is not stored in any data +bases and will not be sold or given to anyone at any time. This is t +he only time you will receive an email from us."; close(MAIL); }
    Also, Mail::Sendmail may be of interest.
Re: $var$cnt problems
by holli (Abbot) on Jul 08, 2005 at 16:33 UTC
    perldoc -f my

    use a hash!


    holli, /regexed monk/
Re: $var$cnt problems
by Transient (Hermit) on Jul 08, 2005 at 16:32 UTC
    Why not use CGI and pull the names using param?

    In the abscence of that:
    for my $cnt (1 .. 5) { if ( eval "\$fmail$cnt" ne "") { open(MAIL,"| $sendmail") or die "Can't open sendmail $!"; print MAIL "To: ", eval "\$fmail$cnt", "\n"; print MAIL "From: $email\n"; print MAIL "Subject: Refer A Friend\n"; print MAIL "Dear ", eval "\$fname$cnt", ",\n\n"; print MAIL "Your friend, $name at $email, visited out site re +cently and thought you would b +e interested..\n\n"; print MAIL "This is NOT spam. This email was sent by someone +who said they knew you. Your +email address is not stored in any databases and will not be sold or given to anyone at any time. This is the only time you wil +l receive an email from us."; close(MAIL); } }
    (untested)
    and (hopefully) before Corion can get to it: this is open to spam attack. Make sure to strip out newlines from your params.

    Updated it to work - but this is evil and dangerous and I don't recommend it and I'm not offering you yak urine I swear. Use CGI
Re: $var$cnt problems
by tphyahoo (Vicar) on Jul 08, 2005 at 16:32 UTC
    Guess: there's something wrong with your code that would become more obvious if you started your script with the scrictures:
    use strict; use warnings;
    Try it.

    UPDATE: Oops, maybe not. Thanks holli.

      If he gets Global symbol "$fmail" requires explicit package name at... strict is already turned on.

      Try it. ;-)


      holli, /regexed monk/