Here's one way
#! perl -sw
use strict;
sub immutable {
print "immutable received args: [ @_ ]\n";
print "Some more stuff\n";
}
## Save a copy of STDOUT
open SAVED, '>&=STDOUT';
close STDOUT;
## Open STDOUT to a variable (ramfile)(Requires 5.8.x)
open STDOUT, '>', \ my( $var ) or die $!;
## Call the sub
immutable( qw[ some args here ] );
## Close the ramfile
close STDOUT;
## Redirect STDOUT back to it's original place
open STDOUT, '>&=SAVED' or die $!;
## Discard the backup
close SAVED;
## Use the captured output
print "The variable \$var now contains:\n'$var'\n";
__END__
C:\test>junk2
The variable $var now contains:
'immutable received args: [ some args here ]
Some more stuff
'
That's a lot of work to avoid using select.
True, but it is guarenteed to work even if someone uses print STDOUT stuff;, when select won't.
The case of that where I got bitten is when you pass \*STDOUT to some module and internally it uses
printf { $self->{fh} } "%s\n", 'stuff';
Which is not a completely uncommon scenario.
I prefer
{
open local *STDOUT, '>', \$buf;
...
}
over
open TEMP, '>', \$buf; my $old_select = select(TEMP); ... select($old_select);
since the former restores STDOUT even in the case of exceptions. The former, however, doesn't work if someone has previously called [doc://select|select]. I guess the comprehensive solution would be:
{
my $old_select = select();
my $handle = on_release { select($old_select); };
open local *STDOUT, '>', \$buf;
select(STDOUT);
...
}
It even handles exceptions thrown by signal handlers.
Updated.
my $handle = on_release { select($old_select); };
What is on_release?
#!/usr/bin/perl
use strict;
use warnings;
my ($buf);
{
local *STDOUT;
open( STDOUT, '>', \$buf ) or die "Write to buffer failed\n";
mysub();
}
print "buffer: $buf\n";
sub mysub{
print "mysub output\n";
}
Output:
---------- Capture Output ---------- > "C:\Perl\bin\perl.exe" _new.pl buffer: mysub output > Terminated with exit code 0.Does that help?
Update: The above requires 5.8 (thanks to [ikegami] for pointing that out).
I get the following message: Use of uninitialized value in concatenation (.)
You're using a version of Perl older than 5.8.0, when open(STDOUT, '>', \$buf) was introduced. Before 5.8, \$buf would be stringified to something like SCALAR(0x1ab2760). The output ends up in a file by that name instead of going to $buf, so $buf is still undefined when you go to inspect it.
Before 5.8, you had to use [mod://IO::String] or [mod://IO::Scalar].
Also, what is the structure under my ($buf); in your code?
It creates a new scope. This causes local *STDOUT; to be undone (thus restoring the original STDOUT) before the last print.
what is the significant of "qw"
qw[ some args here ]
is the same thing as
('some', 'args', 'here')
See perlop.
Which version of perl are you using?
Thank you for your patience. Being a beginner, I appreciate yours and everyone else's help and patience.
Anyway, the code is working as a stand alone so I must be introducing something else that it does not like.
My PERL version is listed as 5.008005 in SunOS 5.8.
On the subject of a new scope. Does that mean I should do the following:
sub1()
{
my $variables;
my $buff;
code
code
code
{
local *STDOUT;
open( STDOUT, '>', \$buf ) or die "Write to buffer ailed\n";
mysub();
}
print "buffer: $buf\n";
more code
}
sub mysub
{
print "mysub output\n";
}
Again, thanks.
MNJ
I fixed that by setting buffer on ($| = 0) just before the local "scope".
Again, thank you.
MNJ
You may view the original node and the consideration vote tally.
perlmonks.org content © perlmonks.org and BrowserUk, chromatic, ikegami, mnj200g, NodeReaper, wfsp
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03