【问题标题】:Can I call Getopts multiple times in perl?我可以在 perl 中多次调用 Getopts 吗?
【发布时间】:2011-06-06 15:14:32
【问题描述】:

我是 perl 的菜鸟,所以请尽量耐心回答我的这个问题。

似乎如果我多次调用 perl Getopts::Long::GetOpts 方法,第二次调用将被完全忽略。

  1. 这正常吗??(为什么)

  2. 这个过程有哪些替代方法?

(实际上我已经编写了一个模块,我在其中进行了 GetOpts 调用,使用我的模块的脚本也尝试这样做,但似乎脚本没有获得所需的选项)

谢谢, 尼拉杰

【问题讨论】:

    标签: perl getopt-long


    【解决方案1】:

    Getopts::Long 在工作时改变@ARGV,这就是它在处理完开关后可以在@ARGV 中留下非开关值的方式。因此,当您拨打第二个电话时,@ARGV 中没有任何内容可供解析,也没有任何有用的事情发生。

    不过有GetOptionsFromArray:

    默认情况下,GetOptions 解析全局数组@ARGV 中存在的选项。一个特殊的条目 GetOptionsFromArray 可用于解析任意数组中的选项。

    因此,如果您需要多次解析列表,则可以在 @ARGV(或其他数组)的副本上使用 GetOptionsFromArray

    【讨论】:

      【解决方案2】:

      我在一个程序中多次从GetOpts::Long 运行GetOptions。我拥有的是一个.optrc 文件,其中包含可以被命令行覆盖的命令行选项。 .cvsrc.exrc 的工作方式大致相同。

      为了做到这一点,我在 .optrc 文件上运行 GetOptions,然后运行 ​​@ARGV 中的内容。在旧版本的 GetOptions 中,我必须保存@ARGV,将.optrc 放入@ARGV,用GetOptions 处理它,然后恢复@ARGV 并在其上运行GetOptions。较新版本的 GetOpts::Long 现在允许您指定数组,而不是仅使用 @ARGV

      【讨论】:

        【解决方案3】:

        复制@ARGV 会让你忙于一次又一次地解析同一组选项。如果这是你想要的,那很好。但是。

        假设您在程序中使用了一组模块,它们只能识别您的@ARGV 的一个子集。您要做的是从每个模块调用 GetOptions,使用模块能够识别的每个选项,并将 @ARGV 中的其余选项留给其他模块处理。

        您可以通过调用配置 Getopt::Long 来执行此操作

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

        但请参阅 perldoc Getopt::Long 了解各种配置的副作用!

        示例:一个脚本 (o1.pl) 能够识别几个选项和两个模块(o1::p1 和 o1::p2),它们必须读取自己的选项

        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 来源(在 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 来源(在 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;
        

        运行 o1.pl:

        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
        

        将为您提供以下(预期的)输出(p1 使用了它的选项,然后 p2 做到了,然后 main 留下了它所知道的):

        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
                };
        

        【讨论】:

        • 这似乎是在回答其他问题。
        • 不,你错了。我发布了我的答案,对 Neeraj 遇到的实际任务做出了一些假设。我在第一段中明确指出,因为我一次又一次地完全解析 @ARGV 而不是在需要的地方传播 opts 对我来说毫无意义。
        【解决方案4】:

        这难道不是关键字“local”应该用于的那种东西吗?

        {
            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;
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-12-10
          • 2020-08-26
          • 2018-07-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多