如何在perl中使用Getopt :: Long lib获取哈希参数数组?

时间:2018-04-05 06:45:29

标签: perl getopt-long

我希望在我的脚本中使用Getopt::Long lib将参数作为哈希数组。 出于示例目的,请考虑以下命令行。

perl testing.pl --systems id=sys_1 ip_address=127.0.0.1 id=sys_2 ip_address=127.0.0.2

为了简单起见,我使用两个系统,并且每个系统只使用两个子参数,即idip_address。理想情况下,systems的数量是动态的,它可能包含1,2或更多,因此每个系统的参数数量都是如此。

我的脚本应该以这样的方式处理这些参数:它将存储在@systems数组中,每个元素都是包含idip_address的哈希。

Getopt::Long lib中是否有任何方法可以实现此目的而不用我自己解析它。

以下是我想要的概念脚本。

testing.pl

use Getopt::Long;
my @systems;
GetOptions('systems=s' => \@systems);
foreach (@systems) {
  print $_->{id},' ', $_->{ip_address};
}

4 个答案:

答案 0 :(得分:2)

我实际上认为这是一个设计问题,而不仅仅是GetOpt的一个问题 - 支持多个配对参数作为命令行参数传递的概念我认为这样做会让你感觉更好避免。

GetOpt并没有真正支持它的原因 - 它实际上不是一个可扩展的解决方案。

如果只是从STDIN读取值?:

#!/usr/bin/env perl

use strict;
use warnings;

use Data::Dumper;

my %systems = do { local $/; <DATA> } =~ m/id=(\w+) ip_address=([\d\.]+)/mg;

print Dumper \%systems; 

然后您就可以调用脚本:

perl testing.pl <filename_with_args>

或类似的。

如果你真的必须:

my %systems = "@ARGV" =~ m/id=(\w+) ip_address=([\d\.]+)/g;

以上两种方法都适用于多个参数。

但是,您对其他帖子的评论:

  

我无法理解,因为我从数据库中获取参数并将其转换为命令行,然后使用系统命令$cmd_lines_args = '--system --id sys_1 --ip_address 127.0.0.0.1'; system("perl testing.pl $cmd_lines_args");将其传递给脚本$ cmd_lines_args我将动态生成通过从数据库中读取来循环

..这使得这是一个XY问题。

不要这样做:

open ( my $script, '|-', "perl testing.pl" );
print {$script} "id=some_id ip_address=10.9.8.7\n";
print {$script} "id=sys2 ip_address=10.9.8.7\n";

等。

答案 1 :(得分:1)

这是一次尝试,可能会有更优雅的解决方案:

GetOptions('systems=s{1,}' => \my @temp );

my @systems;
while (@temp) {
    my $value1 = shift @temp;
    $value1 =~ s/^(\w+)=//; my $key1 = $1;
    my $value2 = shift @temp;
    $value2 =~ s/^(\w+)=//; my $key2 = $1;
    push @systems, { $key1 => $value1, $key2 => $value2 };
}

for (@systems) {
    print $_->{id},' ', $_->{ip_address}, "\n";
}

<强>输出

sys_1 127.0.0.1
sys_2 127.0.0.2

答案 2 :(得分:1)

你在描述什么,

--systems id=sys_1 ip_address=127.0.0.1 id=sys_2 ip_address=127.0.0.2

似乎是一个选项,它采用可变数量的参数作为对,并且是两个的倍数。 Getopt::Long's "Options with multiple values"可让您执行以下操作:

GetOptions('systems=s{2,4}' => \@systems);

这允许你指定2个,3个或4个参数,但它没有#34;任何偶数个参数的语法&#34; (覆盖超过两个的任意数量的对),你仍然需要手动解压缩id=sys_1。您可以编写user-defined subroutine来处理--systems&#39;参数(但不考虑缺少id=... s):

my $system;
my %systems;

GetOptions('systems=s{,}' => sub {
    my $option = shift;
    my $pair = shift;
    my ($key, $value) = split /=/, $pair;

    $system = $value if $key eq 'id';
    $systems{$system} = $value if $key eq 'ip_address';
});

但我更喜欢以下方案之一:

--system sys_1 127.0.0.1 --system sys_2 127.0.0.1
--system sys_1=127.0.0.1 --system sys_2=127.0.0.1

他们通过以下方式实现了目标:

GetOptions('system=s{2}', \@systems);
GetOptions('system=s%', \@systems);

答案 3 :(得分:0)

我只是解析--systems arg并引用这样的“哈希”:

perl testing.pl --systems "id=s1 ip_address=127.0.0.1 id=s2 ip_address=127.0.0.2"

就像这样解析:

my($systems,@systems);
GetOptions('systems=s' => \$systems);
for(split/\s+/,$systems){
    my($key,$val)=split/=/,$_,2;
    push @systems, {} if !@systems or exists$systems[-1]{$key};
    $systems[-1]{$key}=$val;
}
print "$_->{id} $_->{ip_address}\n" for @systems;

打印:

sys_1 127.0.0.1
sys_2 127.0.0.2