使用带有perlcritic的IPC :: Open3

And*_*sev 5 perl perl-critic ipcopen3

我想在子进程中压缩输出并只读取stderr.perlfaq8建议做以下事项:

# To capture a program's STDERR, but discard its STDOUT:
use IPC::Open3;
use File::Spec;
use Symbol qw(gensym);
open(NULL, ">", File::Spec->devnull);
my $pid = open3(gensym, ">&NULL", \*PH, "cmd");
while( <PH> ) { }
waitpid($pid, 0);
Run Code Online (Sandbox Code Playgroud)

但后来perlcritic争论使用裸字文件句柄.

我唯一可以设计的是将select新打开的描述符/dev/null改为on STDOUT,如下所示:

# To capture a program's STDERR, but discard its STDOUT:
use IPC::Open3;
use File::Spec;
use Symbol qw(gensym);
open my $null, ">", File::Spec->devnull;
my $old_stdout = select( $null );
my $pid = open3(gensym, ">&STDOUT", \*PH, "cmd");
select( $old_stdout );
while( <PH> ) { }
waitpid($pid, 0);
Run Code Online (Sandbox Code Playgroud)

但后来perlcritic不喜欢使用select.有更优雅的解决方案吗?

小智 3

最小的更改只是将 open 中的 NULL 更改为 *NULL,使其不再是裸词。

使用这种形式的句柄通常仍然被认为是不好的形式(因为它们是全局变量,尽管您可以通过对它们应用 local 来使它们稍微不那么全局)。所以我建议将其更改为对所有句柄使用我的变量。看起来您正在丢弃标准输入文件句柄,因此也可以传递空文件句柄(请注意,我正在以读写模式打开它)

use strict;
use warnings;

use IPC::Open3;
use File::Spec;
use Symbol qw(gensym);

open(my $null, '+>', File::Spec->devnull);

my $childErr = gensym;

my $pid = open3($null, $null, $childErr, "cmd");

while(<$childErr>) { }
waitpid($pid, 0);
Run Code Online (Sandbox Code Playgroud)