如何在 Perl 中关闭并重新打开 STDOUT?

发布于 2024-11-16 11:29:32 字数 267 浏览 0 评论 0原文

我想关闭 STDOUT 以防止我的代码输出我需要进行进一步计算但不希望出现在我的网页上的特定图像。

所以我想关闭 STDOUT,对代码执行我必须执行的操作,然后重新打开 STDOUT 以将内容输出到网页。 (不是文件)

我尝试的是:

    close STDOUT;
    # my code here
    open STDOUT;

这不起作用......

谢谢

I'd like to close STDOUT to prevent my code from outputing a particular image that I need for further computation but do not want on my web page.

So i want to close STDOUT, do what I have to do with my code, then reopen STDOUT to output stuff to a web page. (Not to a file)

What I tried is:

    close STDOUT;
    # my code here
    open STDOUT;

This doesn't work...

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

霊感 2024-11-23 11:29:32

有多种方法可以解决您的问题,其中许多方法不需要您关闭 STDOUT,也不需要冒破坏程序标准 I/O 通道的风险。

例如,您可以使用 (1-arg) select 命令来指示暂时在其他地方输出 print 命令。

 print $stuff_you_want_to_send_to_STDOUT;

 select(NOT_STDOUT);
 # now default print sends things to NOT_STDOUT.
 # This doesn't need to be a real filehandle, though you may get warning
 # messages if it is not.
 ...;
 print $the_image_you_dont_want_to_go_to_STDOUT;
 ...;

 select(STDOUT);
 # now  print  sends things to STDOUT agin
 print $more_stuff_you_do_want_to_go_to_STDOUT;

您还可以在运行时重新分配*STDOUT glob,而无需关闭任何句柄。

 *OLD_STDOUT = *STDOUT;
 print $for_STDOUT;

 *STDOUT = *NOT_STDOUT;     # again, doesn't need to be a real filehandle
 print $stuff_to_suppress;

 *STDOUT = *OLD_STDOUT;     # restore original STDOUT
 print $more_stuff_for_STDOUT;

There are several ways to approach your problem, and many of them do not require you to close STDOUT and risk fubaring your program's standard I/O channels.

For example, you can use the (1-arg) select command to direct the output of print commands somewhere else temporarily.

 print $stuff_you_want_to_send_to_STDOUT;

 select(NOT_STDOUT);
 # now default print sends things to NOT_STDOUT.
 # This doesn't need to be a real filehandle, though you may get warning
 # messages if it is not.
 ...;
 print $the_image_you_dont_want_to_go_to_STDOUT;
 ...;

 select(STDOUT);
 # now  print  sends things to STDOUT agin
 print $more_stuff_you_do_want_to_go_to_STDOUT;

You can also reassign the *STDOUT glob at run-time without closing any handles.

 *OLD_STDOUT = *STDOUT;
 print $for_STDOUT;

 *STDOUT = *NOT_STDOUT;     # again, doesn't need to be a real filehandle
 print $stuff_to_suppress;

 *STDOUT = *OLD_STDOUT;     # restore original STDOUT
 print $more_stuff_for_STDOUT;
〆凄凉。 2024-11-23 11:29:32

关闭 STDOUT 是不好的,因为很多人都假设它总是打开的。最好将其重定向到 /dev/null (unix) 或 nul (Windows)。

如果你想重定向文件描述符,

use Sub::ScopeFinalizer qw( scope_finalizer );

{
    open(my $backup_fh, '>&', \*STDOUT) or die $!;
    my $guard = scope_finalizer { open(STDOUT, '>&', $backup_fh) or die $!; };
    open(STDOUT, '>', '/dev/null') or die $!;

    ...
}

如果你只想重定向STDOUT,

{
    local *STDOUT;
    open(STDOUT, '>', '/dev/null') or die $!;

    ...
}

如果你只想重定向默认输出句柄,

use Sub::ScopeFinalizer qw( scope_finalizer );

{
    open(my $null_fh, '>', '/dev/null') or die $!;
    my $backup_fh = select($null_fh);
    my $guard = scope_finalizer { select($backup_fh); };

    ...
}

It's bad to close STDOUT since much assumes it's always open. It's better to redirect it to /dev/null (unix) or nul (Windows).

If you want to redirect the file descriptor,

use Sub::ScopeFinalizer qw( scope_finalizer );

{
    open(my $backup_fh, '>&', \*STDOUT) or die $!;
    my $guard = scope_finalizer { open(STDOUT, '>&', $backup_fh) or die $!; };
    open(STDOUT, '>', '/dev/null') or die $!;

    ...
}

If you just want to redirect STDOUT,

{
    local *STDOUT;
    open(STDOUT, '>', '/dev/null') or die $!;

    ...
}

If you just want to redirect the default output handle,

use Sub::ScopeFinalizer qw( scope_finalizer );

{
    open(my $null_fh, '>', '/dev/null') or die $!;
    my $backup_fh = select($null_fh);
    my $guard = scope_finalizer { select($backup_fh); };

    ...
}
椵侞 2024-11-23 11:29:32

您可以实现一些东西来捕获 STDOUT,如下所示:

sub stdout_of (&) {
    my $code = shift;

    local *STDOUT;
    open STDOUT, '>', \(my $stdout_string = '')
        or die "reopen STDOUT: $!";

    $code->();

    return $stdout_string;
}

然后像这样使用它:

my $stdout = stdout_of { print "hello world" };

在 stdout_of() 中本地化文件句柄可以让您避免关闭和重新打开 STDOUT 的技巧。

You can implement something to catch STDOUT like so:

sub stdout_of (&) {
    my $code = shift;

    local *STDOUT;
    open STDOUT, '>', \(my $stdout_string = '')
        or die "reopen STDOUT: $!";

    $code->();

    return $stdout_string;
}

And then use it like so:

my $stdout = stdout_of { print "hello world" };

Localizing the filehandle inside stdout_of() allows you to avoid the tricks of closing and re-opening STDOUT.

卷耳 2024-11-23 11:29:32

阅读open 文档

搜索“这是一个使用各种方法保存、重定向和恢复 STDOUT 和 STDERR 的脚本”。

您想要做的不是关闭 STDOUT,而是暂时将其重定向到 /dev/null。

Read the documentation for open.

Search for "Here is a script that saves, redirects, and restores STDOUT and STDERR using various methods".

What you want to do is not close STDOUT, but rather redirect it to /dev/null temporarily.

骷髅 2024-11-23 11:29:32

要(重新)打开 STDOUT 或 STDERR 作为内存中的文件,请先将其关闭:

 close STDOUT;
    open STDOUT, '>', \$variable or die "Can't open STDOUT: $!";

从 perl 文档: http://perldoc.perl.org/functions/open.html
你有一个 : 结束后,不要这样做。上面的 open 也应该适用于 jus

open STDOUT;

Perl Monks 中的这个线程也可能对您有帮助: http://www.perlmonks.org/?node_id=635010" rel="nofollow">http://www.perlmonks.org perlmonks.org/?node_id=635010

To (re)open STDOUT or STDERR as an in-memory file, close it first:

 close STDOUT;
    open STDOUT, '>', \$variable or die "Can't open STDOUT: $!";

From the perl doc: http://perldoc.perl.org/functions/open.html
You have a : after your close, don't do that. The open above should also work with jus

open STDOUT;

This thread in perl monks might help you too: http://www.perlmonks.org/?node_id=635010

蛮可爱 2024-11-23 11:29:32

我检查了两种方法:

  1. 通过 select
  2. 通过 *OLD_STDOUT = * STDOUT,并发现它们在常见情况下不可用。

原因是只有在 Perl 脚本中使用“print”或其他内容时,这两种方法才会重定向 STDOUT。但是,如果您使用“system()”调用或调用下标,它们的输出无论如何都会达到标准 STDOUT =((。

我的观点是,真正的解决方案是:

#!/usr/bin/perl -w
my $file1 = "/tmp/out.txt";
my $file2 = "/tmp/err.txt";
open my $oldSTDOUT, ">&STDOUT";
open OLDERR, ">&",\*STDERR; 
open(STDOUT, ">$file1")  or print("Can't redirect stdout: to $file1 ");
open(STDERR, ">$file2")  or print("Can't redirect stderr: to $file2 ");
print "THIS OUTPUT ISN'T GOT TO STANDARD OUTPUT\n";
system("pwd"); # this output isn;t got to standard output too, that is right!
close(STDOUT);
close(STDERR);
open STDOUT, ">>&", $oldSTDOUT;
open STDERR, ">>&OLDERR"; 
print "BUT THIS OUTPUT IS SEEN IN A STANDARD OUTPUT\n";

我检查了这个解决方案,它对我有用。

I checked 2 ways:

  1. via select
  2. via *OLD_STDOUT = * STDOUT, and see they are not usable in common case.

The reason is these 2 approachs redirect STDOUT only if "print" or something else is used in a Perl Script. But if you use "system()" call or call subscript, their output got to standard STDOUT anyway =((.

My point of view, the indeed solution is to be:

#!/usr/bin/perl -w
my $file1 = "/tmp/out.txt";
my $file2 = "/tmp/err.txt";
open my $oldSTDOUT, ">&STDOUT";
open OLDERR, ">&",\*STDERR; 
open(STDOUT, ">$file1")  or print("Can't redirect stdout: to $file1 ");
open(STDERR, ">$file2")  or print("Can't redirect stderr: to $file2 ");
print "THIS OUTPUT ISN'T GOT TO STANDARD OUTPUT\n";
system("pwd"); # this output isn;t got to standard output too, that is right!
close(STDOUT);
close(STDERR);
open STDOUT, ">>&", $oldSTDOUT;
open STDERR, ">>&OLDERR"; 
print "BUT THIS OUTPUT IS SEEN IN A STANDARD OUTPUT\n";

I checked this solution and it worked for me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文