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

Hi all,

I have two scripts that I've written that do related features, and I'd like to combine them into one script so that I can run:

perl myscript.plx -dooption1

or perl myscript.plx -dooption2

I don't think it's needed to post the actual scripts here (they're pretty long), but for example if I had:

#!/usr/local/bin/perl print "Hello, world!\n";
And:
#!/usr/local/bin/perl print "Goodbye, world!\n";

How would I go about combining them into one script, that I could run via: 'perl worldscript.plx -goodbye' or 'perl worldscript.plx -hello'?

The scripts I have are a bit more involved than that, and they do two completely different (yet related) things, so I'm looking for a way to take two big scripts and put them in one file, and call either based upon a command line switch.:)

As always, please use small code-newbie words, I'm very new at this and 99% of what I know so far has been from the help that I've gotten from you fine people, and I am very thankful that so many of you have taken the time to help me out. Much appreciation. =)

Thanks!

Replies are listed 'Best First'.
Re: Combining two scripts with a command line switch?
by Joost (Canon) on Dec 13, 2004 at 17:38 UTC
    Although you can read the options directly from the @ARGV array, if you expect any more of them, and you like GNU style options (--longoption == -l), you might want to use the standard Getopt::Long module. Example:

    #!/usr/local/bin/perl -w use Getopt::Long; my ($hello,$goodbye); # option switches GetOptions ( "hello" => \$hello, "goodbye" => \$goodbye, ); if ($hello) { print "Hello world\n"; } if ($goodbye) { print "Goodbye!\n"; }

    # use full options > perl test.pl --hello --goodbye Hello world Goodbye!

    # use abbreviation > perl test.pl -h Hello world

    Getopt::Long can also handle a variety of different option types, with or without arguments etc. See the documentation.

      You guys are the best - that worked! Thanks!

      One more quick question, how do I set it so that an argument is required? Right now I have:
      my ($read,$generate,$help); # option switches GetOptions ( "help" => \$help, "read" => \$read, "generate" => \$generate, );

      If I run the it with any switch, it works perfectly - run it with no arguments, it does nothing at all. :) I'd like to add one more switch for a blank variable, so I can toss in a string that says "type -help for usage'."

      Thanks very much as always!
        how about:
        my ($read,$generate,$help); # option switches GetOptions ( "help" => \$help, "read" => \$read, "generate" => \$generate, ); die "$Usage\n" unless $read || $generate;
        Paul
Re: Combining two scripts with a command line switch?
by mpeters (Chaplain) on Dec 13, 2004 at 17:35 UTC
    It you're asking for help on how to get the command line args then look at GetOpt::Long, GetOpt::Tiny or GetOpt::Mixed for which ever way floats your boat.
Re: Combining two scripts with a command line switch?
by Velaki (Chaplain) on Dec 13, 2004 at 17:32 UTC

    An easy, cheesy, but very workable way, would be to use a big if statement.

    if($command_line_switch =~ /hello/) { # program 1 code } if($command_line_switch =~ /goodbye/) { # program 2 code }

    NOTE:
    I'm assuming that you already know how to process command line switches.

    Vale!
    -v
    "Perl. There is no substitute."
Re: Combining two scripts with a command line switch?
by gaal (Parson) on Dec 13, 2004 at 18:12 UTC
    Before you implement any of the above methods, there's a simple step I think you should take that may save you some trouble:

    Very near the top of each of your two scripts, put the following code:

    use strict; if (! caller) { main(); exit 0; } sub main { # leave some room here. }

    Now, when you run your scripts they will do nothing. Pull in things from the file-level into this new main sub you've created, until each script works exactly as it had worked before (it helps if you already have some regression tests).

    Then, when doing the actual merge, put the code that selects either run mode before this new main (which now you have to call main_script1 and main_script2, only please use better names instead). Put it right there in the if statement, instead of the call to main.

    The purpose of this whole exercise is to keep yourself from forgetting stray code that might have been hiding between subs, and if you hadn't been using strict, prevent global variables that had the same name from each script from interfereing with each other.

    This is really modest advice; but it helps to force you to do cleanups on one front at a time, if they turn out necessary. Of course maybe your code is already squeaky clean and you don't need all this :)

Re: Combining two scripts with a command line switch?
by kesterkester (Hermit) on Dec 13, 2004 at 17:54 UTC

    Here is a snippet using Getopt::Long. You can call the script with a "--run_script" argument (or just "-r"-- Getopt::Long accepts unique abbreviations for flags). You could put an if block after the print statement to control which code, depending on the value of $pars{run_script}:

    #!/usr/bin/perl use warnings; use strict; use Getopt::Long; my %pars = ( run_script => 0 ); GetOptions ( \%pars, 'run_script=f', ); print "Run script $pars{run_script}\n"; allen94-lt 11: ./getopt_ex.pl -r 5 Run script 5 allen94-lt 12: ./getopt_ex.pl Run script 0

    Note the default value (0) that run_script has been given in the creation of the %pars hash. You could change this by changing the original setup of the hash.

    --Kester

Re: Combining two scripts with a command line switch?
by eric256 (Parson) on Dec 13, 2004 at 21:33 UTC

    A solution (although it migh be a BadIdea and misguided would be)

    ### in hello.pl print "Hello"; ### in goodbye.pl print "goodbye"; ### in choose.pl require shift() . ".pl";

    Then fromt he command line perl choose.pl hello would run the hello code, and the same for goodbye. You should definitly verify that the input is a real file that you want to allow them to run etc., but this should get you started down this path. In general i would think it is a bad idea and would rethink what you are doing to see if it fits in some differen t model better.


    ___________
    Eric Hodges