将 perl 的 qx{} / `...` 运算符与参数列表一起使用
use perl's qx{} / `...` operator with a list of arguments
system
、exec
、open '|-'
、open2
等都允许我将 运行 的命令指定为参数列表将通过 shell.
直接传递给 execvp
而不是 运行
即使 perl
足够聪明,可以直接 运行 如果它看起来像一个 "simple" 命令,那也省去了我正确 shell 转义的麻烦争论及其带来的所有令人讨厌的陷阱。
示例:
open my $out, '|-', $prog, @args;
system $prog, @args;
exec $prog, @args;
而不是
open my $out, "|$prog @args";
system "$prog @args";
exec "$prog @args";
qx//
运算符是否有这样的等价物?还是您必须始终手动完成,例如。
sub slurpcmd {
open my $h, '-|', @_ or die "open $_[0]|: $!";
local $/ unless wantarray;
<$h>
}
模块 IPC::System::Simple as the function capturex
(additionally like the other functions in that module, it will throw an exception if there is an execution error or non-zero response code, which you can tweak). Alternatively, you can use Capture::Tiny 提供了 qx 运算符的列表形式来包装核心 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
在核心中,除了 IPC::Open3 之外,管道打开在大多数情况下是唯一的选择,它同样复杂但也允许定向 STDERR。
这里有几个简单的选项。
String::ShellQuote + qx
:
use String::ShellQuote qw( shell_quote );
my $cmd = shell_quote(@cmd);
my $output = `$cmd`;
-
use IPC::System::Simple qw( capturex );
my $output = capturex(@cmd)
-
use IPC::Run3 qw( run3 );
run3(\@cmd, \undef, \my $output);
-
use IPC::Run qw( run );
run(\@cmd, \undef, \my $output);
第一个解决方案涉及 shell,但其他 none。
事实证明(不幸的是)这并不是我的疏忽——唯一的解决方案确实是使用 open -|
或使用其他答案中列出的外部模块之一。
反引号 implementation(无论是由 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);
...
注意 POPpconstx
从堆栈中弹出一个参数,并使用 PerlProc_popen
而不是 PerlProc_popen_list
。
system
、exec
、open '|-'
、open2
等都允许我将 运行 的命令指定为参数列表将通过 shell.
execvp
而不是 运行
即使 perl
足够聪明,可以直接 运行 如果它看起来像一个 "simple" 命令,那也省去了我正确 shell 转义的麻烦争论及其带来的所有令人讨厌的陷阱。
示例:
open my $out, '|-', $prog, @args;
system $prog, @args;
exec $prog, @args;
而不是
open my $out, "|$prog @args";
system "$prog @args";
exec "$prog @args";
qx//
运算符是否有这样的等价物?还是您必须始终手动完成,例如。
sub slurpcmd {
open my $h, '-|', @_ or die "open $_[0]|: $!";
local $/ unless wantarray;
<$h>
}
模块 IPC::System::Simple as the function capturex
(additionally like the other functions in that module, it will throw an exception if there is an execution error or non-zero response code, which you can tweak). Alternatively, you can use Capture::Tiny 提供了 qx 运算符的列表形式来包装核心 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
在核心中,除了 IPC::Open3 之外,管道打开在大多数情况下是唯一的选择,它同样复杂但也允许定向 STDERR。
这里有几个简单的选项。
String::ShellQuote +
qx
:use String::ShellQuote qw( shell_quote ); my $cmd = shell_quote(@cmd); my $output = `$cmd`;
-
use IPC::System::Simple qw( capturex ); my $output = capturex(@cmd)
-
use IPC::Run3 qw( run3 ); run3(\@cmd, \undef, \my $output);
-
use IPC::Run qw( run ); run(\@cmd, \undef, \my $output);
第一个解决方案涉及 shell,但其他 none。
事实证明(不幸的是)这并不是我的疏忽——唯一的解决方案确实是使用 open -|
或使用其他答案中列出的外部模块之一。
反引号 implementation(无论是由 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);
...
注意 POPpconstx
从堆栈中弹出一个参数,并使用 PerlProc_popen
而不是 PerlProc_popen_list
。