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

Hello,

Further to my recent node 474948 i have a question relating to flattened hashes and arrays.

When an array or hash is passed to a subroutine or function it is flattened and so if it is passed as (@, $) and recieved as (@, $) the $ will have no value.

Is this the same with passing to an external script using the exec function.

At the moment i am doing this:

exec = ("BlastTool.cgi", "$date", "$show_filter", "$oldRefFile", "$blast_filehandle", "$ref_filehandle", "$email", "$send_email","$show_all", "\@OrigRef", "\@blastLine", "\@species_filter", "\@chromo_filter", "\@advanced_filter") or die;

In script one, then passing to script 2

my $date = shift @_; my $show_filter = shift @_; my $oldRefFile = shift @_; my $blast_filehandle = shift @_; my $ref_filehandle = shift @_; my $email = shift @_; my $send_email = shift @_; my $show_all = shift @_; my @OrigRef = @{shift @_}; my @blastLine = @{shift @_}; my @species_filter = @{shift @_}; my @chromo_filter = @{shift @_}; my @advanced_filter = @{shift @_};
Is this right or am i way off here.
I have had a look at this node which is asking the same thing but there is no reference to arrays or hashes with using system.

I have also noticed that i have left out the @args at the end of the exec function: exec("program", "params", @args);
Does this matter.

cheers.

Replies are listed 'Best First'.
Re: Passing and recieving params
by merlyn (Sage) on Jul 15, 2005 at 15:58 UTC
      Ok,

      I was trying to get this first script to get the input from either the command line or web page.

      Based on the input, being either two files or a single sequence, one of two scripts would execute, called from within the first cgi script.

      MonkPaul.

        Why don't you convert the script's guts into a module, and write two simple interfaces (CGI and commandline) which use the module?
        # script.cgi use CGI; use BlastTool; ... get info from CGI object ... BlastTool::do_it( $date, $show_filter, ... \@chromo_filter, \@advanced_filter );
        # script.pl use BlastTool; ... prompt the user for the info ... BlastTool::do_it( $date, $show_filter, ... \@chromo_filter, \@advanced_filter );

        Arrays are passed by reference to avoid being flattened.

Re: Passing and recieving params
by ikegami (Patriarch) on Jul 15, 2005 at 16:07 UTC

    Programs can only receive strings as arguments.
    "\@blastLine" will pass the name of the variable (Completly useless).
    "@blastLine" will stringify the contents of @blastLine. "@blastLine" is identical to join($", @blastLine).

    What are you trying to do anyway???

    By the way, if the script you are executing is a CGI script, command line parameters have a special meaning for it. If it's not, you shouldn't end its name with .cgi.

Re: Passing and recieving params
by socketdave (Curate) on Jul 15, 2005 at 16:09 UTC
    When you do an exec() or system() it's just as if you've typed the command on the command line and are passing arguments to it. Figure out how you would call the second script from the command line and emulate that format with exec() or system().

    I also think that your understanding of passing an array to a sub may be a bit off. Whatever you pass to a sub is available as @_ inside the sub. It has indeed been flattened, but if you structure your arguments properly this isn't a problem. If you send it (@,$), then you effectively have the original array with the scalar on the end. To get it back you can just do $my_scalar = pop @_ and then @_ should be identical to the array that you passed.

    UPDATE:
    I also notice that you're using shift @_ in your second script... Remember that the second script is being called from the command line, so your parameters are in @ARGV, not in @_