K
kj
Let me preface this question by making it clear that there's no
particular problem I'm trying to solve, but rather I'm trying to
clarify my understanding of how Perl works, at least under Unix.
In the following snippet, the key fragment is the block labeled
LOOK_HERE. There I first "save" STDOUT by duplicating the handle;
then I redirect STDOUT; then I execute a (forked) command that has
the effect of sending some output to (the now redirected) STDOUT;
and finally I "restore" STDOUT with another duplication.
my $file = 'somefile';
open my $out, '>', $file or die $!;
LOOK_HERE:
{
open my $save, '>&', STDOUT or die $!;
open STDOUT, '>&', $out or die $!;
{
open my $pipe, '|-', '/usr/bin/sort', '-n' or die $!;
print $pipe int( rand( ~0 ) ), "\n" for 1..1_000_000;
}
open STDOUT, '>&', $save or die $!;
}
print "OK\n";
close $out;
my @sorted = map { chomp; $_ } File::Slurp::read_file( $file );
This all works: the output of /usr/bin/sort does end up in 'somefile',
and "OK\n" gets printed to the terminal, confirming that STDOUT
was properly restored.
So far so good.
My question is this: is there a way to avoid the bothersome saving
and restoring of STDOUT. I naively thought that one could do so
by localizing *STDOUT. IOW, replace the LOOK_HERE block with:
{
local *STDOUT;
open STDOUT, '>&', $out or die $!;
{
open my $pipe, '|-', '/usr/bin/sort', '-n' or die $!;
print $pipe int( rand( ~0 ) ), "\n" for 1..1_000_000;
}
}
Very nice, except it doesn't work. Now the output /usr/bin/sort
(which, incidentally, in this example happens to be pretty big)
goes to the terminal. BTW, this same thing happens if instead of
redirecting STDOUT by duplicating the write-handle $out, I simply
re-open STDOUT like this:
{
local *STDOUT;
open STDOUT, '>', 'somefile' or die $!;
{
open my $pipe, '|-', '/usr/bin/sort', '-n' or die $!;
print $pipe int( rand( ~0 ) ), "\n" for 1..1_000_000;
}
}
Ditto if instead I select $out before execution of the sort command.
I suspect that the problem with these failed solutions has to do
with the implicit fork triggered by the '|-' mode in the call to
open. I.e., I'm guessing that the child process uses the default
STDOUT irrespective of the parent's maneuvers. But if this is the
case, then my confusion simply shifts to wondering how the first
approach could have worked at all!
Anyway, BTAIM, is there anyway to avoid the save/restore rigmarole?
TIA!
kj
particular problem I'm trying to solve, but rather I'm trying to
clarify my understanding of how Perl works, at least under Unix.
In the following snippet, the key fragment is the block labeled
LOOK_HERE. There I first "save" STDOUT by duplicating the handle;
then I redirect STDOUT; then I execute a (forked) command that has
the effect of sending some output to (the now redirected) STDOUT;
and finally I "restore" STDOUT with another duplication.
my $file = 'somefile';
open my $out, '>', $file or die $!;
LOOK_HERE:
{
open my $save, '>&', STDOUT or die $!;
open STDOUT, '>&', $out or die $!;
{
open my $pipe, '|-', '/usr/bin/sort', '-n' or die $!;
print $pipe int( rand( ~0 ) ), "\n" for 1..1_000_000;
}
open STDOUT, '>&', $save or die $!;
}
print "OK\n";
close $out;
my @sorted = map { chomp; $_ } File::Slurp::read_file( $file );
This all works: the output of /usr/bin/sort does end up in 'somefile',
and "OK\n" gets printed to the terminal, confirming that STDOUT
was properly restored.
So far so good.
My question is this: is there a way to avoid the bothersome saving
and restoring of STDOUT. I naively thought that one could do so
by localizing *STDOUT. IOW, replace the LOOK_HERE block with:
{
local *STDOUT;
open STDOUT, '>&', $out or die $!;
{
open my $pipe, '|-', '/usr/bin/sort', '-n' or die $!;
print $pipe int( rand( ~0 ) ), "\n" for 1..1_000_000;
}
}
Very nice, except it doesn't work. Now the output /usr/bin/sort
(which, incidentally, in this example happens to be pretty big)
goes to the terminal. BTW, this same thing happens if instead of
redirecting STDOUT by duplicating the write-handle $out, I simply
re-open STDOUT like this:
{
local *STDOUT;
open STDOUT, '>', 'somefile' or die $!;
{
open my $pipe, '|-', '/usr/bin/sort', '-n' or die $!;
print $pipe int( rand( ~0 ) ), "\n" for 1..1_000_000;
}
}
Ditto if instead I select $out before execution of the sort command.
I suspect that the problem with these failed solutions has to do
with the implicit fork triggered by the '|-' mode in the call to
open. I.e., I'm guessing that the child process uses the default
STDOUT irrespective of the parent's maneuvers. But if this is the
case, then my confusion simply shifts to wondering how the first
approach could have worked at all!
Anyway, BTAIM, is there anyway to avoid the save/restore rigmarole?
TIA!
kj