使用Perl`' cmd' .join ...`在反引号中表达

时间:2015-03-31 08:33:18

标签: perl

我想将剩余的@ARGV发送给foo。我目前这样做:

my $cmd = 'foo '.join ' ', @ARGV;
my $out = `$cmd`;

有可能在一行中完成吗?例如,使用不存在的e选项:

my $out = qx/'foo'.join ' ', @ARGV/e;

在更一般的情况下,我可能想要这样做:

my $out = qx/'foo?.join(' ', keys %hash)/e;

3 个答案:

答案 0 :(得分:2)

在运行命令之前,您无需组装命令。 qx()运算符(由反引号别名)进行插值。

 perl -e 'print `echo @ARGV`' foo bar

或在您的脚本中:

my $out = `foo @ARGV`

关于qx的“可选”是什么,插值是正确的:请注意双插值可能会让你感到烦恼,而且很容易出现安全问题!

关于您的更新:尝试

perl -e '%h = (foo=>1,bar=>2); print `echo @{[keys %h]}`'

构造一个匿名的arrayref并立即对它进行derefferrence。散列不进行插值,但此数组上下文允许任意Perl代码生成列表。另外我很确定编译器会识别这个习惯用法并在优化过程中删除arrayref(de)dereferrence。

但从我的观点来看,这真的很难看,几乎无法辨认。我宁愿推荐:

my @keys = keys %hash;
my $cmd  = "foo @keys";
my $out  = `$cmd`;

提示:将命令存储在专用变量中会使日志记录更容易执行真正所需的命令。

答案 1 :(得分:2)

内置readpipe函数位于反引号/ qx()调用的后端,因此您可以直接使用它:

my $out = readpipe('foo' . join ' ', @ARGV);

答案 2 :(得分:1)

当然

my $out = capture_this_command( 'foo', @ARGV );

sub capture_this_command {
    use Capture::Tiny qw/ capture /;
##    local %ENV;
##    delete @ENV{'PATH', 'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
##    $ENV{'PATH'} = '/bin:/usr/bin';

    my @cmd = @_;
    my( $stdout, $stderr, $exit ) = capture { 
        system { $cmd[0] } @cmd;
    };;

    if( $exit ){
        die "got the exit( $exit ) and stderr: $stderr\n   ";
    } elsif( $stderr ){
        warn "got stderr: $stderr\n   ";
    }

    return $stdout;
}

<强>更新 qx //是双引号,它是插值的,所以perlintro / perlsyn / perlquote 的所有内容都会说,但是,请记住,qx //调用你的shell(看看你有哪一个{{1} }}和shell有自己的插值

所以你可以写perl -V:sh但它的插值,首先是perl,然后是你调用的任何shell