gpt4 book ai didi

r - 在 perl 中打开管道时直接使用 STDERR

转载 作者:行者123 更新时间:2023-12-02 05:27:35 25 4
gpt4 key购买 nike

我正在使用 open( my $command_out, "-|", $command_string ) 来执行命令并即时处理其输出(不必先等待命令完成,如 system()).

我注意到,当我以这种方式调用一些 R 脚本时,一些 R 消息会打印到屏幕上(例如 Loading required package: ...)。我猜这是因为 R 将此输出发送到 stderr(?尽管这些并不是真正的错误)。

是否可以在 open() 时将此输出也定向到 $command_out,以便屏幕保持干净?

最佳答案

假设你的 R 程序是

#! /usr/bin/env r

require(Hmisc)

cat(argv[1], "\n")

结果出人意料地健谈:

$ ./prog.r fooLoading required package: HmiscLoading required package: methodsLoading required package: survivalLoading required package: statsLoading required package: utilsLoading required package: graphicsLoading required package: splinesAttaching package: 'Hmisc'    The following object(s) are masked from package:survival :     untangle.specials     The following object(s) are masked from package:base :     format.pval,     round.POSIXt,     trunc.POSIXt,     units foo

From here, you could discard the standard error or merge it with another stream.

Discarding the standard error

One way to discard the standard error is to use a shell redirect of 2>/dev/null. This is a general mechanism, and 2 is the standard error's file descriptor. For example:

#! /usr/bin/perl

use warnings;
use strict;

open my $command_out, "-|", "./prog.r foo 2>/dev/null"
or die "$0: could not start prog.r";

while (<$command_out>) {
print "got: $_";
}

shell 还将处理 backtick or qx//表达式

#! /usr/bin/perl

use warnings;
use strict;

(my $command_out = `./prog.r foo 2>/dev/null`) =~ s/^/got: /mg;
print $command_out;

和一个标量命令传递给system

#! /usr/bin/perl

use warnings;
use strict;

system("./prog.r foo 2>/dev/null") == 0
or warn "$0: prog.r exited " . ($? >>8);

对于所有这些,输出是

$ ./prog.pl got: foo

But sometimes you don't want the shell putting its grubby mitts on your command. Maybe it contains shell metacharacters or quotes that you don't want to deal with escaping. This is when a safe pipe-open is useful:

#! /usr/bin/perl

use warnings;
use strict;

my $pid = open my $command_out, "-|";
die "$0: fork: $!" unless defined $pid;

if ($pid == 0) {
# child
open STDERR, ">", "/dev/null" or die "$0: open: $!";
exec "./prog.r", "foo & bar" or exit 1; # STDERR silent now
}

while (<$command_out>) {
print "got: $_";
}

close $command_out or warn "$0: prog.r exited " . ($? >> 8);

"-|" 上打开句柄会 fork 一个子句柄并将子句柄的标准输出连接到该句柄。喜欢fork ,它向子进程返回 0,向父进程返回一个非零进程标识符,或者在失败时返回未定义的值。

在 child 中,我们首先将STDERR重定向到/dev/null,然后使用exec用我们的 R 程序替换 child 。请注意,我们以列表形式传递命令以绕过 shell:

If there is more than one argument in LIST, or if LIST is an array with more than one value, calls execvp(3) with the arguments in LIST.

因为我们再也看不到标准错误了,所以显式关闭 $command_out 以检查 child 是否愉快地运行很重要。否则,您会遇到令人费解的静默失败。

样本运行:

$ ./prog.pl got: foo & bar

Merge STDERR into STDOUT

To see the standard error on your handle, use 2>&1 instead, e.g.,

open my $command_out, "-|", "./prog.r foo 2>&1" or die;

通过安全管道打开,dup 标准错误到标准输出:

if ($pid == 0) {
# child
open STDERR, ">&", \*STDOUT or die "$0: open: $!";
exec "./prog.r", "foo & bar" or die "$0: exec: $!";
}

open文档涵盖了这一点:

You may also, in the Bourne shell tradition, specify an EXPR beginning with >&, in which case the rest of the string is interpreted as the name of a filehandle (or file descriptor, if numeric) to be duped (as dup(2)) and opened.

即使您可以通过这种方式看到标准错误,使用close 检查子进程的退出状态仍然是个好主意。

现在一切都通过$command_out到达:

got: Loading required package: Hmiscgot: Loading required package: methodsgot: Loading required package: survivalgot: Loading required package: statsgot: Loading required package: utilsgot: Loading required package: graphicsgot: Loading required package: splinesgot: got: Attaching package: 'Hmisc'got: got: got:    The following object(s) are masked from package:survival :got: got:     untangle.specials got: got: got:    The following object(s) are masked from package:base :got: got:     format.pval,got:     round.POSIXt,got:     trunc.POSIXt,got:     units got: got: foo & bar

关于r - 在 perl 中打开管道时直接使用 STDERR,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3486575/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com