Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
File 将stdout和stderr管道化到文件中的子例程_File_Perl_Io_Stream - Fatal编程技术网

File 将stdout和stderr管道化到文件中的子例程

File 将stdout和stderr管道化到文件中的子例程,file,perl,io,stream,File,Perl,Io,Stream,如果我有一个名为simplecalc.pl的程序: 是否有一种方法可以将支持文件的冗长处理以可重用的方式放入模块中?支持文件由用户发送给程序维护人员 注:上述解决方案也适用于simplecalc.pl 4 0 1,这将导致除法槽0。在主程序使用的任何模块中捕获一个骰子,并将骰子消息写入支持文件是一项重要功能。我猜您正在寻找select,它会更改打印时的默认文件处理程序。在程序结束之前运行的 use v5.10; use warnings; use strict; my($OK,$UNKNOWN)

如果我有一个名为simplecalc.pl的程序:

是否有一种方法可以将支持文件的冗长处理以可重用的方式放入模块中?支持文件由用户发送给程序维护人员


注:上述解决方案也适用于simplecalc.pl 4 0 1,这将导致除法槽0。在主程序使用的任何模块中捕获一个骰子,并将骰子消息写入支持文件是一项重要功能。

我猜您正在寻找select,它会更改打印时的默认文件处理程序。在程序结束之前运行的

use v5.10; use warnings; use strict;
my($OK,$UNKNOWN)=(1,0);

my($filename, $endmsg, $exit) = ('my.log', 'OK', $OK);
END { say $endmsg }
my $DEFAULT_FH=select;  #select returns current default file handler (often STDOUT)
if( rand()<0.5){        #half the time, for test
    open my $FH, '>>:utf8', $filename or die; #append
    $endmsg = qq{support-info successfully written into $filename};
    $exit = $UNKNOWN;
    select $FH;
}

print "print something\n";
say   "say something more"; #same as print except \n is added

if(1){
    select $DEFAULT_FH;     #or just:  select STDOUT
}
exit $exit;

我想通过这个问题来控制来自模块的两个流的重定向

像这个基本的例子

下午六时四十五分

main.pl

控制台上的输出已对齐

Hello from main WARN from main at ... line 18. Hi to STDOUT again WARN in main again at ... line 29. 而其他的_streams.log有两行代码。如果它们在控制台上卷起,标签可以很容易地找到

在本例中,管理文件句柄的责任在于调用方

这应该通过各种各样的错误检查来完成,subs中的选项只重定向一个流,或者每个流都重定向到自己的文件,等等,可能还有一些更方便的例程

请注意,$stdout=*stdout创建了一个别名

另一种保存STDOUT以备日后修复的方法是


这将创建一个独立的文件句柄,作为STDOUT的副本,这正是我们在这里所需要的,它不受STDOUT的更改或关闭的影响。请参阅使用示例。

我看不出您需要什么-在get_support(获取支持)下,它可以重定向流而不写任何东西吗?但另一次,它切换回来。在所需的模块中,我看不到write_support_文件写入该文件的内容,只有恢复的标准输出的消息。你能说明目的吗?你是对的,这个问题的措辞和布局不是最佳的。我将使用@kjetil-s答案中的元素重写它。谢谢,更清楚了。我仍然不确定总体目的,请看我的答案,如果需要请告诉我谢谢你花时间猜我需要什么!我已经用你关于结束块的提示重写了上面的问题。我在我的示例simplecalc.pl中使用了你的重定向流,它工作得很好-非常感谢!关于您提出的关于总体用途的问题:我正在交付一个包含许多脚本的应用程序-所有这些脚本都有这些冗长且难以维护的代码,以允许用户编写支持文件。我想把它放在一个地方。您的示例现在是进一步集中该支持文件任何方面的起点。@lanti Great:另一个选项是让模块中的sub打开文件本身,以便调用方只传递文件名。这需要更多的注意、检查等。还有,什么显示可能会或可能不会?我很感兴趣。
package RedirectStreams;

use warnings;
use strict;

use Exporter qw(import);
our @EXPORT_OK = qw(redirect_streams restore_streams);

our ($stdout, $stderr) = (*STDOUT, *STDERR);

sub redirect_streams {
    my ($handle) = @_;
    *STDOUT = $handle;
    *STDERR = $handle;
}

sub restore_streams {
    *STDOUT = $stdout;
    *STDERR = $stderr;
}

1;
use warnings;
use strict;

use RedirectStreams qw(redirect_streams restore_streams);

my $logfile = shift @ARGV  || 'streams.log';

say "Hello from ", __PACKAGE__;            
warn "WARN from ", __PACKAGE__;

open my $fh, '>', $logfile;
    
redirect_streams($fh);

say "\tHi to redirected";
warn "\tWARN to redirected";

restore_streams();
    
say  "Hi to STDOUT again";
warn "WARN in main again";

open my $fh_other, '>', 'other_' . $logfile;
redirect_streams($fh_other);
say  "STDOUT redirected to another";
warn "STDERR redirected to another";

close $_ for $fh, $fh_other;
Hello from main WARN from main at ... line 18. Hi to STDOUT again WARN in main again at ... line 29. Hi to redirected WARN to redirected at ... line 24.
open my $stdout, '>&', STDOUT;