Reputation: 703
Suppose we have:
sub test {
print "testing\n";
}
If there is a case where I want to have it print to stderr instead of stdout, is there a way I can call the subroutine to do this? Or can I capture the output to a variable and then use warn? I'm fairly new to perl.
Upvotes: 8
Views: 3889
Reputation: 2743
This work for me
local *STDOUT;
open(STDOUT, ">", \$Result);
&test();
print $Result;
Upvotes: 1
Reputation: 5619
Meanwhile, you can also "capture a subroutine's print output to a variable."
Just pass a scalar ref to open
:
#! /usr/bin/env perl
use common::sense;
use autodie;
sub tostring (&) {
my $s;
open local *STDOUT, '>', \$s;
shift->();
$s
}
sub fake {
say 'lalala';
say 'more stuff';
say 1 + 1, ' = 2';
say for @_;
}
for (tostring { fake(1, 2, 3) }) {
s/\n/\\n/g;
say "Captured as string: >>>$_<<<";
}
Output:
Captured as string: >>>lalala\nmore stuff\n2 = 2\n1\n2\n3\n<<<
Upvotes: 3
Reputation: 58524
Perl's dynamic scoping via local() is not often used, but this strikes me as a good application for it:
test(); # to stdout
{
open(local *STDOUT, ">&STDERR") or die "dup out to err: $!";
test(); # to stderr, locally calling it "STDOUT"
}
test(); # to stdout again
The call to test()
in the block above -- as well as to anything that test()
itself might call -- will have STDOUT dynamically scoped to your duplicate of STDERR. When control leaves the block, even if by die()
ing, STDOUT will be restored to whatever it was before the block
Generalized:
sub out2err(&) {
my $user_block = shift;
open(local *STDOUT, ">&STDERR") or die $!;
$user_block->();
}
test(); # to stdout
out2err { test() }; # to stderr
test(); # to stdout
Upvotes: 10
Reputation: 118595
Yes there is. print
sends its output to the "selected" filehandle, which is usually STDOUT
. But Perl provides the select
function for you to change it.
select(STDERR);
&test; # send output to STDERR
select(STDOUT); # restore default output handle
The select
function returns the previously selected filehandle, so you can capture it and restore it later.
my $orig_select = select(STDERR);
&test;
select($orig_select);
Upvotes: 12