2010-11-23 28 views
2

我有吐出如下一行shell脚本:如何使用Getopt :: Long解析可能有空格的参数?

prog_name -options ... 

具体而言,作为一个例子:

prog_name -filter_arg +define BOOST +noconvtest +actuate-long -disp_arg +define size=40 res=30

请注意,上面有没有报价,我做没有控制权来修改shell脚本。 [但是,我不确定是否可以通过其他程序将引号插入到上述语法中。]。

现在,我想上面发送到Perl程序来解析选项,以便它关联 +define BOOST +noconvtest +actuate-long的选项-filter_arg+define size=40 res=30的选项-disp_arg

有人可以帮我做这个吗?

回答

0

我不是100%确定的,但我不认为你可以使用GetOpt :: Long来做到这一点,至少不是直接。

你会需要我认为做第一遍自己,像

my @filters; 
my $filter = []; 

foreach (@ARGV) { 
    if ($_ eq '+filter') { 
    push @filters, $filter; 
    $filter = []; 
    } else { 
    push @$filter, $_; 
    } 
} 
push @filters, $filter if @$filter; 

foreach (@filters) { 
    Getopt::Long::GetOptionsFromArray(@$_, ... 

    ... 
} 
+0

非常感谢Axeman,David和Colin。非常感谢您的及时回应。按照Perl的真实精神,您已经展示了如何以多种方式解决问题!我仔细了解了您的每一个帖子后,我学到了很多东西。温暖的问候。 – Silver2010 2010-11-24 03:25:38

2

你可以传递一个回调,像这样:

use strict; 
use warnings; 
use Getopt::Long; 

my $options = {}; 
@ARGV=qw<-filter_arg +define BOOST +noconvtest +actuate-long -disp_arg +define size=40 res=30>; 
GetOptions( 
    $options # store in hash ref 
    , qw<filter_arg define=s noconvtest actuate-long> 
    , disp_arg => sub { 
     # this will contain "+define size=40 res=30" 
     $options->{disp_arg} = join(' ', delete @ARGV[0..$#ARGV]); 
     } 
    ); 
5

Getopt::Long简单解析@ARGV列表作为提供到Perl程序。如果@ARGV列表中的参数是单独的条目,则Getopt::Long将以这种方式解析它们。你的问题是shell将每个参数作为一个单独的参数,因为它们周围没有引号。

您的选择是你的Perl脚本运行之前,或改写(munging)@ARGV本身的参数组合成他们假设是在值要么Munge时间参数。

对于第一种选择,你可以使用sed将您的程序输出并添加缺少的引号。如果你是程序总是吐出领域是这样的:

prog_name -filter_arg +define BOOST +noconvtest +actuate-long -disp_arg +define size=40 res=30 

,你可以管,通过sed这样的:

$ orig_prog | sed -e 's/filter_arg /filter_arg "/' -e 's/ -disp_arg /" -disp_arg "/' -e 's/$/"/' 

或者这样:

$ orig_prog | sed -e 's/^\(.*\) -filter_arg \(.*\) -disp_arg \(.*\)$/\1 -filter_arg "\2" -disp_arg "\3"/' 

,将放在引号围绕您的参数,它将如下所示:

prog_name -filter_arg "+define BOOST +noconvtest +actuate-long" -disp_arg "+define size=40 res=30" 

这样,@ARGV将正确设置,因此GetOptions函数将以您希望的方式工作。

的另一种方式是Munge时间@ARGV一旦你打电话之前Perl程序运行GetOptions

my $value; 
my @newArgv; 
foreach my $param (@ARGV) { 
    if ($param =~ /^-/) { 
    if ($value) { 
    push (@newArgv, $value); 
    $value = ""; 
    } 
    push(@newArgv, $param); 
    } else { 
    $value = $value ? "$value $param" : "$param"; 
    } 
} 
push (@newArgv, $value) if ($value); 
@ARGV = @newArgv; 

在上面的例子中,@ARGV将具有以下值:

@ARGV[0] = -filter_arg 
@ARGV[1] = +define BOOST +noconvtest +actuate-long 
@ARGV[2] = -disp_arg 
@ARGV[3] = +define size=40 res=30 

而且,Getopts::Long现在应该按照您希望的方式工作。 有点旁注:在较新版本的Getopt::Long中,除了@ARGV之外,您还可以使用其他数组。你只需把你想要作为第一个参数使用数组中GetOptions

use Getopt::Long qw(GetOptionsFromArray); 

GetOptionsFromArray (
    \@newArgs, 
    "filter_arg=s" => \$filter_arg, 
    "disp_arg=s" => \$disp_arg, 
); 
0

的Getopt ::龙可以解析您的命令行是:

my (@filter_arg, @display_arg); 
GetOptions('filter_arg=f{1,5}' => \@filter_arg, 'display_arg=i{1,5}' => \@display_arg); 

你会得到PARMS的阵列。

请参阅Getopt::Long - Options with multiple values,以获取有关多值参数处理的更详细解释。