开发者

Can I call Getopts multiple times in perl?

开发者 https://www.devze.com 2023-03-10 13:30 出处:网络
I am a noob to perl, so please try to be patient with this question of mine. It seems that if I make multiple ca开发者_如何学Golls to perl Getopts::Long::GetOpts method, the second call is completely

I am a noob to perl, so please try to be patient with this question of mine.

It seems that if I make multiple ca开发者_如何学Golls to perl Getopts::Long::GetOpts method, the second call is completely ignored.

  1. Is this normal??(Why)

  2. What are the alternatives to this process??

(Actually Ive written a module, where I make a GetOpts call, an the script using my module tries to do that too, but it seems that script does not get the required options)

Thanks, Neeraj


Getopts::Long alters @ARGV while it works, that's how it can leave non-switch values behind in @ARGV when it is done processing the switches. So, when you make your second call, there's nothing left in @ARGV to parse and nothing useful happens.

However, there is GetOptionsFromArray:

By default, GetOptions parses the options that are present in the global array @ARGV. A special entry GetOptionsFromArray can be used to parse options from an arbitrary array.

So you could use GetOptionsFromArray on a copy of @ARGV (or some other array) if you need to parse the list multiple times.


I've run GetOptions from GetOpts::Long multiple times in a single program. What I have is a .optrc file that contains command line options that can be overridden by the command line. Much the same way .cvsrc and .exrc work.

In order to do that, I run GetOptions on the .optrc file and then what's in @ARGV. In older versions of GetOptions, I had to save @ARGV, toss .optrc into @ARGV, process it with GetOptions, and then restore @ARGV and run GetOptions on that. Newer versions of GetOpts::Long now allow you to specify the array instead of using just @ARGV.


Making copies of @ARGV will keep you busy parsing again and again the same set of options. If this is what you want, fine. But.

Suppose you have a set of modules you are using in your program which can recognize only a subset of your @ARGV. What you want to do is to call GetOptions from each of these module, consume each of the options the module is able to recognize and leave the rest of the options in @ARGV to be processed by the other modules.

You can configure Getopt::Long to do this by calling

Getopt::Long::Configure qw/pass_through/;

But see perldoc Getopt::Long for various configurations side effects!

Example: a script (o1.pl) able to recognize few options and two modules (o1::p1 and o1::p2) which must get to read their own options

o1.pl:

!/usr/bin/perl

use Getopt::Long;

use o1::p1;
use o1::p2;
# now o1::p1 and o1::p2 already consumed recognizable options
#no need to configure pass_through since main:: will get to see only its options
#Getopt::Long::Configure(qw/pass_through/);

my %main_options = ( 'define' => {}, );
print "main: \@ARGV = " . join (', ', @ARGV) . "\n";
GetOptions(\%main_options, "main-vi=i","verbose",'define=s');

use Data::Dumper;
print "main_options: ", Dumper(\%main_options);
print "p1 options: ", Dumper(\%o1::p1::options);
print "p2 options: ", Dumper(\%o1::p2::options);
exit 0;

o1::p1 source (in o1/p1.pm):

package o1::p1;
use Getopt::Long;
Getopt::Long::Configure qw/pass_through/;

%options = ();
print "package p1: \@ARGV = " . join (', ', @ARGV) . "\n";;

GetOptions(\%options, "p1-v1=s", "p1-v2=i");


1;

o1::p2 source (in o1/p2.pm):

package o1::p2;
use Getopt::Long;
Getopt::Long::Configure 'pass_through';

%options = ();
print "package p2: \@ARGV=". join (', ', @ARGV). "\n";
GetOptions(\%options, "p2-v1=s", "p2-v2=i");

1;

running o1.pl with:

perl o1.pl  --main-vi=1 --verbose  --define a=ss --p1-v1=k1 --p1-v2=42 --define b=yy --p2-v1=k2  --p2-v2=66

will give you the following (expected) output (p1 consumed its options, then p2 did it, then main was left with what it knows about):

package p1: @ARGV = --main-vi=1, --verbose, --define, a=ss, --p1-v1=k1, --p1-v2=42, --define, b=yy, --p2-v1=k2, --p2-v2=66
package p2: @ARGV=--main-vi=1, --verbose, --define, a=ss, --define, b=yy, --p2-v1=k2, --p2-v2=66
main: @ARGV = --main-vi=1, --verbose, --define, a=ss, --define, b=yy
main_options: $VAR1 = {
          'verbose' => 1,
          'define' => {
                        'a' => 'ss',
                        'b' => 'yy'
                      },
          'main-vi' => 1
        };
p1 options: $VAR1 = {
          'p1-v1' => 'k1',
          'p1-v2' => 42
        };
p2 options: $VAR1 = {
          'p2-v1' => 'k2',
          'p2-v2' => 66
        };


Isn't this the sort of the thing the keyword "local" is supposed to be for?

{
    local @ARGV = @ARGV;
    our $opt_h;
    &getopts('h');
    &printUsage if $opt_h;
}


# Now that the local version of @ARGV has gone out of scope, the original version of @ARGV is restored.

while (@ARGV){
    my $arg = shift @ARGV;
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号