Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Wrap multiple programs

by jnarayan81 (Sexton)
on Mar 18, 2017 at 00:41 UTC ( [id://1185096]=perlquestion: print w/replies, xml ) Need Help??

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

How to wrap multiple programs in one main program?

perl Main.pl plot -file FILE -length LENGTH

perl Main.pl calc -length 20 -width 30

So Main.pl contains two sub-programs 'plot' and 'calc'. User can call anyone of them, based on their need.

################# PLOT program here #!/usr/bin/perl -w use Getopt::Long; my $data = "file1"; my $length = 4; my $verbose; GetOptions ( "length=i" => \$length, "file=s" => \$data, "verbose" => \$verbose ); if (!@ARGV) { print "$0: Argument required.\n"; exit 1 } my $fh = read_fh ($data); while (<$fh>) { print "$_\n"; } ##sub here # Open and Read a file sub read_fh { my $filename = shift @_; my $filehandle; if ($filename =~ /gz$/) { open $filehandle, "gunzip -dc $filename |" or die $!; } else { open $filehandle, "<$filename" or die $!; } return $filehandle; } ################# CALC program here #!/usr/bin/perl -w use Getopt::Long; my $width = 5; my $length = 4; my $verbose; GetOptions ( "width=i" => \$width, "length=i" => \$length, "verbose" => \$verbose ); if (!@ARGV) { print "$0: Argument required.\n"; exit 1 } my $total=$width*$length; print $total;

Replies are listed 'Best First'.
Re: Wrap multiple programs
by Athanasius (Archbishop) on Mar 18, 2017 at 06:43 UTC

    Hello jnarayan81,

    We can solve any problem by introducing an extra level of indirection.the fundamental theorem of software engineering

    You can achieve your stated goal by adding a suitable command-line option and refactoring accordingly:

    But, really, this is a bad idea. It won’t scale well, and in any case, what does it gain? It’s actually easier for a user to enter:

    perl calc.pl --length 20 --width 30

    than

    perl main.pl --function calc --length 20 --width 30

    and by keeping the scripts separate, you avoid the complications that arise from having overlapping options. (For example, what if you want the --length option to default to 10 when plotting but to 20 when calculating? Then you would need to have separate options:

    ... my $plotlength = 10; my $calclength = 20; ... GetOptions ( ... 'plotlength=i' => \$plotlength, 'calclength=i' => \$calclength, ... ) or die "Error in command line arguments\n";

    This could get messy very quickly.)

    So, it’s best to follow stevieb’s advice and modularise your code as much as possible.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      For example, what if you want the --length option to default to 10 when plotting but to 20 when calculating?

      Solution a) Leave value undefined for now. (use topic-specific default value when you branch into that code)

      my $opt_length; GetOptions ( "length=i" => \$opt_length, ); # call plot() or calc() sub plot { my $length = opt_length // 10; ... } sub calc { my $length = opt_length // 20; ... }

      Solution b) Only parse the first argument to decide which route to take and then hand over the rest of @ARGV to the next level -> http://perldoc.perl.org/Getopt/Long.html#Parsing-options-from-an-arbitrary-array

Re: Wrap multiple programs
by stevieb (Canon) on Mar 18, 2017 at 00:53 UTC

    You can not get command line options twice within the same program. I recommend writing both Plot and Calc into subroutines within the main script, and go from there.

    Otherwise, create a module out of both of the mentioned "things" into modules, import them into your main script, then distribute the cli arguments appropriately.

      To the OP: Although below I'll show a way to put multiple commands on one command line, I actually don't necessarily recommend this, nor would I recommend building a monolithic "one script to do it all", instead follow stevieb's and Athanasius's advice to modularize. One element of the Unix philosophy is to make each tool "Do One Thing and Do It Well". If your scripts need to share common functions, then do that through a module, rather than shoving all the code into one script.

      You can not get command line options twice within the same program.

      That statement is just a little too absolute for my tastes, it's totally possible to get too clever with @ARGV :-)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1185096]
Approved by Athanasius
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2024-04-20 00:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found