如果我有一个名为simplecalc.pl
的程序:
use v5.10;
use warnings;
use strict;
# SIMPLE CALCULATOR
# Usage: simplecalc.pl <n1> <n2> [<verbose> <logswitch>]
# Example Usage:
# normal usage : simplecalc.pl 4 2
# verbose usage : simplecalc.pl 4 2 1
# support-case usage: simplecalc.pl 4 2 0 1
my($OK,$UNKNOWN)=(0,3);
my($filename, $endmsg, $exit) = ('my.log', undef, undef);
my($n1, $n2, $DEBUG, $GET_SUPPORT_FILE) = @ARGV;
# Handling of the support-file starts here ===============================
*ORIGINAL_STDOUT = *STDOUT;
if ($GET_SUPPORT_FILE) {
$DEBUG = 1;
$endmsg = "support-info sucessfully written into $filename";
$exit = $UNKNOWN;
# redirect stdout and stderr
open my $stdout_txt, '>>:utf8', "$filename";
*STDOUT = $stdout_txt;
open STDERR, '>&STDOUT';
} else {
$endmsg = "Finnished calculation - good bye.";
$exit = $OK;
}
END {
select *ORIGINAL_STDOUT;
say $endmsg;
};
# end of support-file handling ============================================
say STDERR "INFO: got $n1 and $n2 from the commandline" if $DEBUG;
say "Hello, let me calc the quotient from $n1 trough $n2 for you ...";
my $quotient = $n1 / $n2;
say "Quotient: $quotient";
exit $exit;
有没有办法将支持文件的冗长处理以可重用的方式放入模块中? (支持文件应由用户发送给程序维护者。)
注意:上述解决方案也适用于simplecalc.pl 4 0 0 1
,导致除法为0.在主程序使用的任何模块中捕获die
并将die-msg写入支持 - 文件是一个重要的功能。
答案 0 :(得分:2)
我猜你正在寻找select
,它会更改print
和say
中的默认文件处理程序。并且END
在程序结束之前运行。
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 filehandler (often STDIN)
if( rand()<0.5){ #half the time, for test
open my $FH, '>>:utf8', $filename or die;
$endmsg = qq{support-info sucessfully written into $filename};
$exit = $UNKNOWN;
select $FH;
}
print "Something something\n";
say "Something say something more";
if(1){
select $DEFAULT_FH; #or just: select STDIN
}
exit $exit;
答案 1 :(得分:2)
我提出这个问题想要控制来自模块的两个流的重定向。
像这个基本的例子吗?
<强> RedirectStreams.pm 强>
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;
<强> main.pl 强>
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.
,而文件streams.log
有
Hi to redirected WARN to redirected at ... line 24.
和other_streams.log
有两行。 (如果它们在控制台上结束,则可以轻松找到它们。)
此示例中管理文件句柄的责任在于调用者。
这应该通过各种错误检查,subs中的选项(仅重定向一个流,或者每个都重定向到自己的文件等)以及可能的一些便利例程来完成。