使用perl的qx {} /`...`运算符和参数列表

Căc*_*rău 5 perl backticks qx

system,exec,open '|-',open2,等方面都让我来指定作为将直接传递到参数列表运行命令execvp通过一个外壳,而不是运行.

即使perl它足够聪明,如果它看起来像一个"简单"的命令,它可以直接运行它,这样可以省去正确的shell转义所带来的所有令人讨厌的陷阱的麻烦.

例:

open my $out, '|-', $prog, @args;
system $prog, @args;
exec $prog, @args;
Run Code Online (Sandbox Code Playgroud)

代替

open my $out, "|$prog @args";
system "$prog @args";
exec "$prog @args";
Run Code Online (Sandbox Code Playgroud)

qx//运营商是否有这样的等价物?或者你必须总是手工完成,例如.

sub slurpcmd {
   open my $h, '-|', @_ or die "open $_[0]|: $!";
   local $/ unless wantarray;
   <$h>
}
Run Code Online (Sandbox Code Playgroud)

Gri*_*nnz 5

的操作者QX的列表形式由模块提供IPC ::系统::简单的函数capturex(另外像模块中的其他功能,如果存在一个执行错误或非零响应代码将抛出异常,你可以调整).或者,您可以使用Capture :: Tiny来包装核心system调用并提供相同的行为,但它也有其他功能可以将STDERR包装在一起或与STDOUT分开.

use strict;
use warnings;
use IPC::System::Simple 'capturex';
my $output = capturex $prog, @args;

use Capture::Tiny 'capture_stdout';
my ($output, $exit) = capture_stdout { system $prog, @args };
# standard system() error checking required here
Run Code Online (Sandbox Code Playgroud)

在核心中,管道打开在很大程度上是唯一的选择,除了IPC :: Open3,它同样复杂但也允许指向STDERR.


ike*_*ami 5

这里有一些简单的选择.

第一个解决方案涉及一个shell,但没有其他解决方案.


小智 1

事实证明(不幸的是)这并不是我的疏忽——唯一的解决方案实际上是使用open -|其他答案中列出的外部模块之一来实现这一点。

反引号实现(无论是由qx/.../`...`或调用readpipe)是深入硬连线以接受单个字符串参数:

PP(pp_backtick)
{
    dSP; dTARGET;
    PerlIO *fp;
    const char * const tmps = POPpconstx;
    const U8 gimme = GIMME_V;
    const char *mode = "r";

    TAINT_PROPER("``");
    if (PL_op->op_private & OPpOPEN_IN_RAW)
        mode = "rb";
    else if (PL_op->op_private & OPpOPEN_IN_CRLF)
        mode = "rt";
    fp = PerlProc_popen(tmps, mode);
    ...
Run Code Online (Sandbox Code Playgroud)

请注意,它POPpconstx从堆栈中弹出单个参数,并使用PerlProc_popen代替PerlProc_popen_list