用Getopt :: Long解析参数的最干净方法

时间:2018-12-03 12:22:55

标签: perl

我使用GetOpt解析命令行参数。我想添加一个新的选项“ multi”,它应该得到一个看起来像以下的字符串:key1=abc,key2=123,key3=xwz。 我不知道用户要提供多少个自定义键,但他可以提供minimax 5个键。另外,我想将其放入带有键的哈希中。 我正在寻找一种好方法来实现它。

对于初学者,我曾考虑使用--multi {key1=abc,key2=123,key3=xwz},但由于某种原因,它只能 第一个键key1=abc。我也尝试过:--multi {key1=abc},{key2=123},{key3=xwz},但感觉有点混乱。我想让用户可以像-那样用key1=./some_script.pl --help添加参数。部分代码:

my %arg;
GetOptions(
            "multi=s" => \$arg{"multi"},
}

然后,我想以某种方式将这些键放在哈希中,以便于使用。因此,我想到了使用$arg{"multi"}{"key3"}来获取key3的值。 我应该如何使用此功能?这样做最干净的方法是什么?

总结一下:

  1. 在不使用文件的情况下(要求提供选项,而不是以文件方式),要求用户提供密钥以达到与key1=abc,key2=123,key3=xwz类似的情况的最佳方法是什么?含义-作为脚本的用户,您希望如何提供这些字段?
  2. 如何验证用户提供的密钥少于5个?
  3. 我应该如何解析这些键,以及将这些键插入到multi键的哈希图中的最佳方法是什么。

预期的输出:我希望有一个像这样的哈希:$arg{"multi"}{"key3"}并返回xwz

2 个答案:

答案 0 :(得分:2)

以下程序从命令行上的--multi选项中读取逗号分隔的子选项。

#!perl
use strict;
use warnings;
use Data::Dumper;
use Getopt::Long 'GetOptionsFromArray';

my @args = ('--multi', '{key1=abc,key2=123,key3=xwz}', 'some', 'other');

my %arg;
GetOptionsFromArray(
    \@args,
            "multi=s" => \$arg{"multi"},
);

if( $arg{multi} and $arg{multi} =~ /^\{(.*)\}$/) {
    # split up into hash:
    $arg{ multi } = { split /[{},=]/, $1 };
};

print Dumper \%arg;

__END__

$VAR1 = {
          'multi' => {
                       'key2' => '123',
                       'key1' => 'abc',
                       'key3' => 'xwz'
                     }
        };

该程序使用GetOptionsFromArray以简化测试。在实际程序中,您可能会使用GetOptions(...),它与GetOptionsFromArray(\@ARGV, ...)相同。

答案 1 :(得分:2)

一种方法是将key=value格式的选项分配给哈希,即GetOpt::Long allows。更好的是,由于此功能仅需要哈希引用,因此您可以将其分配给更深的数据结构中的值的hashref。您可以直接使用

use warnings;
use strict;
use feature 'say';

use Getopt::Long;
use Data::Dump qw(dd);

my %args;
$args{multi} = {}; 

GetOptions( 'multi=s' => $args{multi} ) or die "Bad options: $!";

dd \%args;

通过多次调用该选项,将添加键值对

script.pl --multi k1=v1 --multi k2=v2

和上面的程序打印

{ multi => { k1 => "v1", k2 => "v2" } }

我使用Data::Dump打印复杂数据。如果有问题,请更改为核心Data::Dumper

尽管Getopt::Long有一种方法可以限制选项所采用的参数数量,这些参数显然仅适用于数组目标。因此,您必须数数键来检查。

另一种方法是转到process the input string in a subroutine,在这里您几乎可以做任何您想做的事情。将其添加到上面的脚本中,以将另一个带有其hashref的键添加到%args

use warnings;
use strict;
use feature 'say';

use Getopt::Long;
use Data::Dump qw(dd);

my %args;
$args{multi} = {};

GetOptions(
    'multi=s' => $args{multi},
    'other=s' => sub { $args{other} = { split /[=,]/, $_[1] }  }
) or die "Bad options: $!";

dd \%args;

当称为

script.pl --multi k1=v1 --multi k2=v2  --other mk1=mv1,mk2=mv2

此打印

{
  other => { mk1 => "mv1", mk2 => "mv2" },
  multi => { k1 => "v1", k2 => "v2" },
}