FAQ
Hi all especially Perl teachers if anyone is ... :-)

I just want to know if someone can provide some explanation on how does the
argument iterator sub-routine below work. The Perl script is called from a
UNIX Korn script as below:

mail_smtp.pl -r ${MAILFROM} -s "$subject_line TEST EMAIL"
supportmail@test.com < /tmp/test_email.txt

The Perl script is working and SMTP mail is working. Am just trying to
understand how the getval sub-routine is parsing the command line arguments.
the getval subroutine is as below.

=================================================================

sub getval {
my $refVal = '';
foreach $var(@ARGV) {
if ($refVal ne '') {
$$refVal = $var;
$refVal = '';
}
else {
$_ = $var;
if (/-r/ ) {
$refVal=\$fromUser;
}
elsif (/-f/) {
$refVal=\$dataFile;
}
elsif (/-s/) {
$refVal=\$subject;
}
else {
@toUser = split(/[\;,]/,$var);
}

}
}
}

=================================================================

The portion that am confused at is at the following lines:

$$refVal = $var;

and

$_ = $var;
if (/-r/ ) {
$refVal=\$fromUser;
}

Does "if (/-r/ )" means "ignore" all command line that begins with a hyphen
but reference by value the next command line argument after them?

Does $_ contains the following values on each iteration?

mail_smtp.pl
-r
${MAILFROM}
-s
"$subject_line TEST EMAIL"
supportmail@test.com
<
/tmp/test_email.txt

Any "explanation" on this will be very much appreciated. Am going nuts
trying to understand how the iteration functions although am glad it is
functioning.

Thanks in advance.


===============================
mail_smtp.pl source code below:
===============================

#!/usr/bin/perl -w
use Net::SMTP;
use FileHandle;


# global variables
my $fromUser = $ENV{USER};
my @toUser = {};
my $smtpSvr = '192.168.3.11';
my $subject = '';
my $dataFile = '';
#$mailBody = '';
sub getval {
my $refVal = '';
foreach $var(@ARGV) {
if ($refVal ne '') {
$$refVal = $var;
$refVal = '';
}
else {
$_ = $var;
if (/-r/ ) {
$refVal=\$fromUser;
}
elsif (/-f/) {
$refVal=\$dataFile;
}
elsif (/-s/) {
$refVal=\$subject;
}
else {
@toUser = split(/[\;,]/,$var);
}

}
}
}

# main
getval(@ARGV);
if (@toUser ne {}) {

if ($dataFile eq '') {
$dataFile = '-';
}
open(my $inFile, "< $dataFile");
$smtp = Net::SMTP->new($smtpSvr);
$smtp->mail($fromUser);
$smtp->to(@toUser);
$smtp->data();
$smtp->datasend("From:$fromUser\n");
$smtp->datasend("To:".join(';',@toUser)."\n");
if ($subject ne '') {
$smtp->datasend("Subject:$subject\n");
}
while (<$inFile>) {
if (/^\.$/) {
last;
}
else {
$smtp->datasend($_);
}

}
close($inFile);
$smtp->dataend();
$smtp->quit;
}

Search Discussions

  • Jim Gibson at Jul 21, 2010 at 6:55 pm
    On 7/21/10 Wed Jul 21, 2010 10:17 AM, "newbie01 perl"
    <newbie01.perl@gmail.com> scribbled:
    Hi all especially Perl teachers if anyone is ... :-)

    I just want to know if someone can provide some explanation on how does the
    argument iterator sub-routine below work. The Perl script is called from a
    UNIX Korn script as below:

    mail_smtp.pl -r ${MAILFROM} -s "$subject_line TEST EMAIL"
    supportmail@test.com < /tmp/test_email.txt

    The Perl script is working and SMTP mail is working. Am just trying to
    understand how the getval sub-routine is parsing the command line arguments.
    the getval subroutine is as below.

    =================================================================

    sub getval {
    my $refVal = '';
    foreach $var(@ARGV) {
    if ($refVal ne '') {
    $$refVal = $var;
    $refVal = '';
    }
    else {
    $_ = $var;
    if (/-r/ ) {
    $refVal=\$fromUser;
    }
    elsif (/-f/) {
    $refVal=\$dataFile;
    }
    elsif (/-s/) {
    $refVal=\$subject;
    }
    else {
    @toUser = split(/[\;,]/,$var);
    }

    }
    }
    }

    =================================================================

    The portion that am confused at is at the following lines:

    $$refVal = $var;
    That line assigns (copies) the contents of the $var variable to the location
    referenced by the $refVal pointer. This will be either $fromUser, $dataFile,
    or $subject, depending upon the option entered (-r, -f, or -s,
    respectively).
    and

    $_ = $var;
    if (/-r/ ) {
    $refVal=\$fromUser;
    }
    The above lines copy the contents of $var to $_, tests if $_ contains the
    string '-r', and, if it does, sets $refVal to 'refer' to $fromUser.

    A better form would be to test $var directly:

    if( $var =~ /-r/ ) {
    $refVal = \$fromUser;
    }
    Does $_ contains the following values on each iteration?
    $var, and hence $_ (since it is a copy of $var), will contain the elements
    of the @ARGV array, one per iteration of the foreach loop.

    If you use the GetOptions module, you can replace the getval subroutine with
    something like this (untested):

    use Getopt::Long;

    GetOptions(
    'r=s' => \$fromUser,
    'f=s' => \$dataFile,
    's=s' => \$subject
    );
    push(@toUser, split/[;,]/) for @ARGV;
  • John W. Krahn at Jul 21, 2010 at 7:26 pm

    newbie01 perl wrote:
    Hi all especially Perl teachers if anyone is ... :-)

    I just want to know if someone can provide some explanation on how does the
    argument iterator sub-routine below work. The Perl script is called from a
    UNIX Korn script as below:

    mail_smtp.pl -r ${MAILFROM} -s "$subject_line TEST EMAIL"
    supportmail@test.com< /tmp/test_email.txt

    The Perl script is working and SMTP mail is working. Am just trying to
    understand how the getval sub-routine is parsing the command line arguments.
    the getval subroutine is as below.

    =================================================================

    sub getval {
    my $refVal = '';
    foreach $var(@ARGV) {
    if ($refVal ne '') {
    $$refVal = $var;
    $refVal = '';
    }
    else {
    $_ = $var;
    if (/-r/ ) {
    $refVal=\$fromUser;
    }
    elsif (/-f/) {
    $refVal=\$dataFile;
    }
    elsif (/-s/) {
    $refVal=\$subject;
    }
    else {
    @toUser = split(/[\;,]/,$var);
    }

    }
    }
    }

    =================================================================

    The portion that am confused at is at the following lines:

    $$refVal = $var;

    and

    $_ = $var;
    if (/-r/ ) {
    $refVal=\$fromUser;
    }
    When @ARGV is at the '-r' element the $refVal=\$fromUser assigns a
    reference from $fromUser to the variable $refVal and then the next time
    through the loop when @ARGV is the element just past '-r' $fromUser is
    dereferenced through $$refVal and is assigned the current element of @ARGV.

    You are probably better off just using Getopt::Std

    Does "if (/-r/ )" means "ignore" all command line that begins with a hyphen
    but reference by value the next command line argument after them?
    In this case "if (/-r/ )" is just short for "if ($var =~ /-r/ )" but for
    some "cute" reason the programmer decided to use $_ instead of $var.

    Also, /-r/ matches the string '-r' *anywhere* in $_, not just at the
    beginning. It would more properly be written as "if (/\A-r\z/ )" or
    even "if ( $_ eq '-r' )".

    Does $_ contains the following values on each iteration?

    mail_smtp.pl
    -r
    ${MAILFROM}
    -s
    "$subject_line TEST EMAIL"
    supportmail@test.com
    <
    /tmp/test_email.txt

    Any "explanation" on this will be very much appreciated. Am going nuts
    trying to understand how the iteration functions although am glad it is
    functioning.

    Thanks in advance.


    ===============================
    mail_smtp.pl source code below:
    ===============================

    #!/usr/bin/perl -w
    use warnings;
    use strict;
    use Net::SMTP;
    use FileHandle;


    # global variables
    my $fromUser = $ENV{USER};
    my @toUser = {};
    This is assigning a hash reference to the first element of @toUser which
    makes little sense.

    my $smtpSvr = '192.168.3.11';
    my $subject = '';
    my $dataFile = '';
    #$mailBody = '';
    sub getval {
    my $refVal = '';
    foreach $var(@ARGV) {
    if ($refVal ne '') {
    $$refVal = $var;
    $refVal = '';
    }
    else {
    $_ = $var;
    if (/-r/ ) {
    $refVal=\$fromUser;
    }
    elsif (/-f/) {
    $refVal=\$dataFile;
    }
    elsif (/-s/) {
    $refVal=\$subject;
    }
    else {
    @toUser = split(/[\;,]/,$var);
    }

    }
    }
    }

    # main
    getval(@ARGV);
    This is passing the array @ARGV to the @_ array inside the subroutine
    but you don't use the @_ array inside the subroutine so why do it?

    if (@toUser ne {}) {
    That statement is useless and doesn't do what the programmer seems to
    think it is doing. An array in scalar context will return the number of
    elements in the array, which at this point is 1. So '1' will be
    compared to the textual representation of an anonymous hash which is
    something like 'HASH(0x9ec8818)' and the two will *never* be equal.

    Even if the programmer just compared the first element of @toUser to an
    anonymous hash they would *never* be equal.

    What the programmer should have done is define the array without any
    elements:

    my @toUser;

    And then test the array is scalar context to see if getval() populated
    the array:

    if ( @toUser ) {

    if ($dataFile eq '') {
    $dataFile = '-';
    }
    open(my $inFile, "< $dataFile");
    You should *always* verify that the file was opened correctly before
    using its filehandle.

    $smtp = Net::SMTP->new($smtpSvr);
    $smtp->mail($fromUser);
    $smtp->to(@toUser);
    $smtp->data();
    $smtp->datasend("From:$fromUser\n");
    $smtp->datasend("To:".join(';',@toUser)."\n");
    if ($subject ne '') {
    $smtp->datasend("Subject:$subject\n");
    }
    while (<$inFile>) {
    if (/^\.$/) {
    last;
    }
    else {
    $smtp->datasend($_);
    }

    }
    close($inFile);
    $smtp->dataend();
    $smtp->quit;
    }


    John
    --
    Any intelligent fool can make things bigger and
    more complex... It takes a touch of genius -
    and a lot of courage to move in the opposite
    direction. -- Albert Einstein
  • Brandon McCaig at Jul 22, 2010 at 4:53 pm

    On Wed, Jul 21, 2010 at 1:17 PM, newbie01 perl wrote:
    Does $_ contains the following values on each iteration?

    mail_smtp.pl
    -r
    ${MAILFROM}
    -s
    "$subject_line TEST EMAIL"
    supportmail@test.com
    <
    /tmp/test_email.txt
    Just to clarify the end of the command line:

    mail_smtp.pl -r ${MAILFROM} \
    -s "$subject_line TEST EMAIL" \
    supportmail@test.com < /tmp/test_email.txt

    The '< /tmp/test_email.txt' part is not extra arguments passed to the
    script. That is a file redirection operator in the shell[1], used to
    write the file to the script's standard input stream. The script
    accepts an option -f to specify the file to retrieve the message data
    from, but if none is specified then it defaults to - which is
    basically an alias for STDIN.[2]

    The same thing can be accomplished with a pipe:

    cat /tmp/test_email.txt | mail_smtp.pl -r ${MAILFROM} \
    -s "$subject_line TEST EMAIL" supportmail@test.com

    So the script wouldn't see arguments equal to '<' or
    '/tmp/test_email.txt'. The shell will handle those for it automatically.


    [1] http://en.wikipedia.org/wiki/Redirection_(computing)
    [2] perldoc -f open

    --
    Brandon McCaig <bamccaig@gmail.com>
    V zrna gur orfg jvgu jung V fnl. Vg qbrfa'g nyjnlf fbhaq gung jnl.
    Castopulence Software <http://www.castopulence.org/> <bamccaig@castopulence.org>
  • Newbie01 perl at Jul 24, 2010 at 2:19 am
    Hi Brandon,

    Thanks ... using the cat and pipe looks "cleaner" ... I will try that one
    ... thanks
    On Fri, Jul 23, 2010 at 4:53 AM, Brandon McCaig wrote:
    On Wed, Jul 21, 2010 at 1:17 PM, newbie01 perl wrote:
    Does $_ contains the following values on each iteration?

    mail_smtp.pl
    -r
    ${MAILFROM}
    -s
    "$subject_line TEST EMAIL"
    supportmail@test.com
    <
    /tmp/test_email.txt
    Just to clarify the end of the command line:

    mail_smtp.pl -r ${MAILFROM} \
    -s "$subject_line TEST EMAIL" \
    supportmail@test.com < /tmp/test_email.txt

    The '< /tmp/test_email.txt' part is not extra arguments passed to the
    script. That is a file redirection operator in the shell[1], used to
    write the file to the script's standard input stream. The script
    accepts an option -f to specify the file to retrieve the message data
    from, but if none is specified then it defaults to - which is
    basically an alias for STDIN.[2]

    The same thing can be accomplished with a pipe:

    cat /tmp/test_email.txt | mail_smtp.pl -r ${MAILFROM} \
    -s "$subject_line TEST EMAIL" supportmail@test.com

    So the script wouldn't see arguments equal to '<' or
    '/tmp/test_email.txt'. The shell will handle those for it automatically.


    [1] http://en.wikipedia.org/wiki/Redirection_(computing)
    [2] perldoc -f open

    --
    Brandon McCaig <bamccaig@gmail.com>
    V zrna gur orfg jvgu jung V fnl. Vg qbrfa'g nyjnlf fbhaq gung jnl.
    Castopulence Software <http://www.castopulence.org/> <
    bamccaig@castopulence.org>

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupbeginners @
categoriesperl
postedJul 21, '10 at 5:17p
activeJul 24, '10 at 2:19a
posts5
users4
websiteperl.org

People

Translate

site design / logo © 2021 Grokbase