Getopt::Long 只是解析提供给 Perl 程序的@ARGV 列表。如果参数是@ARGV 列表中的单独条目,Getopt::Long 将以这种方式解析它们。您的问题是 shell 将每个参数作为单独的参数,因为它们周围没有引号。
您的选择是在 Perl 脚本运行之前修改参数,或者修改 @ARGV 本身以将参数组合成它们应该包含的值。
对于第一个选项,您可以使用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 函数将按照您希望的方式工作。
另一种方法是在 Perl 程序运行后再调用 @ARGV,然后再调用 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,
);