【问题标题】:Cleanest way to parse argument with Getopt::Long使用 Getopt::Long 解析参数的最简洁方法
【发布时间】:2019-02-01 11:08:20
【问题描述】:

我使用 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

【问题讨论】:

  • --multi key1=abc --multi key2=123 --multi key3=xwz 可以接受吗?此外,--multi {key1=abc,key2=...} 也应该可以工作并且(取决于你的 shell 的变幻莫测)给你完整的价值。如果不是,请根据您的 shell 引用该值:--multi "{key1=abc,key2=...}"。学习如何在 shell 中引用值与 Perl 无关。
  • @ikegami 是的,对不起。虽然很清楚。 @Corion 我们想用一个标志来实现,因为它确实看起来很“漂亮”,有多个相同的标志。另外,我想在不强制用户使用引号" 的情况下实现。
  • @TTaJTa4 - 你不需要引号。您还可以使用反斜杠或单引号,具体取决于您使用的 shell 类型。但是适当地引用大括号是你的 shell 而不是 Perl 的问题。所以,也许告诉我们你使用什么外壳。
  • @Corion 我想我会引用引号。如果命令行是--multi "key1=abc,key2=123,key3=xwz",我该如何解析输入(插入arg 哈希)。
  • 如果您有一个用=, 分隔的字符串,并且您想保持顺序,则不能使用哈希。如果您不关心订单,请使用$arg{ multi } = { split /[=,]/, $args{ multi }};

标签: perl


【解决方案1】:

以下程序从命令行的--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, ...) 相同。

【讨论】:

【解决方案2】:

一种方法是将key=value 格式的选项分配给哈希,即GetOpt::Long allows。更好的是,因为这个功能只需要一个哈希引用,事实证明你可以让它分配给一个哈希引用,它是一个更深的数据结构中的值。你可以直接使用它

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

上面的程序打印出来

{ 多 => { 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

打印出来

{ 其他 => { mk1 => "mv1", mk2 => "mv2" }, 多 => { k1 => "v1", k2 => "v2" }, }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多