0

I have two Perl scripts. Let's call them one.pl and two.pl.

one.pl processes some data and needs to call two.pl, passing a variable.

In one.pl I can

require "two.pl"

to call the second script.

That works fine, but I want to pass a CGI variable to two.pl.

Is there any way to do this without rewriting two.pl as a Perl module?

For example what I want is:

one.pl

...

require "two.pl $number";

two.pl

use CGI;

my $cgi = new CGI;

my $number = $cgi->param('number');

...

EDIT: two.pl should only ever be called once

5
  • 1
    Is $number already a CGI param, or a different value? Commented Jan 4, 2018 at 17:55
  • 1
    @mob your answer was almost correct. Commented Jan 4, 2018 at 17:59
  • For starters, don't use require for .pl files. You should be using do. Commented Jan 4, 2018 at 18:33
  • "Is there any way to do this without rewriting the second script as a module?" Doing that rewrite is almost certainly the correct option, but a lot depends on what two.pl actually does. There is a pitfall with the require solution and it is the wrong choice. Persisting with it may suit your purposes, but you are condemning others to deal with hard-to-find bugs. Commented Jan 5, 2018 at 18:52
  • I think we need to see what one.pl and two.pl contain so that we can better understand what you're trying to do. If you can reduce it to just a few lines of code that we can run ourselves then that would be excellent! Commented Jan 5, 2018 at 19:30

1 Answer 1

1

If one.pl is not in a CGI environment

If your one.pl is a shell script, you can set @ARGV before the call to require. This abuses CGI's mode to work with command line arguments. The arg needs to be the param name equals the value.

{
    my $number = 5;
    local @ARGV = ( "number=$number" );
    require "two.pl";
}

The key=value format is important. The local keyword makes sure that @ARGV is only set inside the block, making sure other possible arguments to your script are not permanently lost, but rather invisible to two.pl.

If one.pl is in a CGI environment

  • If the param is already there, you don't have to do anything.
  • Else, see above.

Note that for both of these you can only ever require a script once. That's the idea of require. Perl keeps track of what it's loaded already (in %INC). If you are in an environment like mod_perl, or a modern Perl application that runs persistently, you should use do "two.pl" instead, which will execute it every time. But then that might break other things if two.pl is not designed to be ran multiple times in the same process.

Your best bet is to refactor the code inside two.pl into a module, and use that in both scripts.

Sign up to request clarification or add additional context in comments.

11 Comments

Thanks @simbabque. I got it to work by editing one.pl to use CGI as well.
@simbabque: Embarrassingly it hadn't hit me that this required a shell, but my "or the equivalent" was meant to include system 'two.pl', "number=$number" which should be implemented within perl. I also question the use of require, which inappropriately searches @INC and adds to %INC, but most importantly will not execute the file again if there is a %INC entry that matches. require is meant only to load definitions, and it doesn't work for executable code. You need do (or system or backticks) and I've had to give you a down vote.
@simbabque: I would also say that "because we are not executing it in a new shell" is an unfounded assumption: it is your choice for a solution. The OP says "I want to pass a CGI variable to the second script" so it sounds like just one environment variable needs to be communicated. There's certainly no reason to stay within the current process apart from the obvious overhead of starting a new process for whatever two.pl does.
@simbabque: I also think that, given the OP's apparent expertise, you should be careful to define what you mean by "in a CGI environment". Anyone who understands process environments pretty much have the answer already.
Fair enough @borodin. Better?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.