如何在perl中删除shell命令运行的未使用参数?

时间:2013-05-27 19:08:41

标签: perl bash

我的脚本从文本文件中获取各种参数的一组值,并将它们放入变量中。然后,运行以下行以使用各种选项执行shell命令:

cmd -a $a -b $b -c $c;

但是,我应该如何处理未定义某些参数的情况?假设-c是可选的,因此用户在文本文件中将其留空。现在,如果代码运行,它将执行

$a = "foo";
$b = "bar"; 
$c = "";
`cmd -a $a -b $b -c $c ` ; # this evaluates to "cmd -a foo -b bar -c" 

由于-c需要参数而给出错误。如果没有实现if语句来考虑变量定义的每个可能情况,是否有一种干净的方法来处理这个问题?

感谢。

4 个答案:

答案 0 :(得分:4)

use String::ShellQuote qw( shell_quote );

$a = ...;
$b = ...;
$c = ...;

my @cmd = 'cmd';
push @cmd, '-a' => $a if length($a);
push @cmd, '-b' => $b if length($b);
push @cmd, '-c' => $c if length($c);
my $cmd = shell_quote(@cmd);
`$cmd`

如果参数顺序无关紧要,那么使用哈希而不是单独的变量会更有意义。

use String::ShellQuote qw( shell_quote );

my %args = (
   '-a' => ...,
   '-b' => ...,
   '-c' => ...,
);

my @cmd = ( 'cmd', map { $_ => $args{$_} } grep length($args{$_}), keys(%args) );
my $cmd = shell_quote(@cmd);
`$cmd`

答案 1 :(得分:3)

您可以使用哈希,然后过滤掉长度为零的参数

my %arg = (
  a => $a,
  b => $b,
  c => $c,
);
my $cmd_args = 
  join " ", 
  map { "-$_ $arg{$_}" }
  grep { length $arg{$_} > 0 }
  sort keys %arg;

`cmd $cmd_args`;

答案 2 :(得分:1)

让我直截了当地说:

  1. 您运行Perl脚本。
  2. Perl脚本为命令行脚本获取或创建了许多选项。
  3. 然后使用这些选项运行可执行文件。
  4. 我会将您的选项放入Perl哈希并使用命令行参数键入,并且该值将是该命令行参数的值。

    my %parameters;
    $parameters{"-a"} = "foo";
    $parameters{"-b"} = "bar";
    $parameters{"-c"} = "";
    

    现在,让我们构建执行命令。我将通过keys命令解析数组。这将返回我循环中可能%parameters哈希的所有键:

    my $command = "cmd";
    
    for my $param ( sort keys %parameters ) {
        if ( $parameters{ $param } ) {
            $command .= " $param $parameters{$param}";
        }
    }
    

    请注意,如果您不需要命令中的任何值,请$parameters{ $param } is blank or zero, it will not add that parameter/value pair to the command line you're executing. Now, we can execute the command. Use system`。然后检查以确保执行有效:

    my $error = system "$command";
    if ( $error ) {
        die qq(Error detected in running command "$command");
    }
    

    如果参数可能为null,有空格或零值,我们必须采取略微不同的机智:

    my %parameters;
    $parameters{"-a"} = "foo";
    $parameters{"-b"} = "bar";
    $parameters{"-c"} = undef;
    
    my $command = "cmd";
    
    for my $param ( sort keys %parameters ) {
        if ( defined $parameters{ $param } ) {
            $command .= qw/ $param "$parameters{$param}"/;
        }
    }
    
    my $error = system "$command";
    if ( $error ) {
        die qq(Error detected in running command "$command");
    }
    

答案 3 :(得分:0)

我会使用各种Getopt模块之一来读取命令行并将条目放入变量中。通常,带参数的选项也将定义一个默认值,或者如果没有给出参数,它将使变量未定义。

当perl文件执行时,它将填写变量,然后你可以从这些参数构造命令行,你可以使用如下逻辑:

push @cmd, "mycmd";
push @cmd, "-a", $opta;
push @cmd, "-b", $optb;
push @cmd, "-c", $optc if defined $optc; # Possibly leave out defined.
system @cmd;