in reply to Re^2: Reassign STDOUT/STDERR contents to a variable
in thread Reassign STDOUT/STDERR contents to a variable

AHA! I just ran into the same problem in some code I'm writing: I had assigned to the "in memory" variable after opening it. Turns out you can only concatenate to it, otherwise you have to seek to the beginning. Some examples:

# Save old STDIN and STDOUT open my $oldin, '<&', \*STDIN or die "Can't dup STDIN:$!"; open my $oldout, '>&', \*STDOUT or die "Can't dup STDOUT:$!"; # set up new STDIN my $invar = "foo\n"; close STDIN; open STDIN, '<', \$invar or die "Can't open scalar:$!"; # set up new STDOUT my $outvar; close STDOUT; open STDOUT, '>', \$outvar or die "Can't open scalar:$!"; # Try it out! print <>; print STDERR $out; # prints "foo" # But beware: # $invar = "bar\n"; #BAD! try this instead: $invar .= "bar\n"; print STDERR <>; #Would have given your manpage. Now works! # This might work, too, but I'm not sure: $invar = "baz\n"; seek STDIN, 0, 0; print STDERR <>; #Not tested, should print "baz\n"; # Another caveat about STDOUT: $outvar = ""; #This does not do what you think. print "ding\n"; print STDERR $outvar; #prints same as "foo\nding\n" # instead, do this: seek STDOUT, 0, 0; print "dong\n"; print STDERR $outvar; # this does print "dong\n" only. # Now restore old filehandles: close STDIN; open STDIN, '<&', $oldin or die "Can't redup STDIN\n"; close $oldin; close STDOUT; open STDOUT, '<&', $oldout or die "Can't redup STDOUT\n"; close $oldout;

UPDATE: the seek on STDIN works just fine. I decided to go that route because it scales better (always concatenating to my input scalar would keep increasing my memory usage.

print pack("A25",pack("V*",map{1919242272+$_}(34481450,-49737472,6228,0,-285028276,6979,-1380265972)))

Replies are listed 'Best First'.
Re^4: Reassign STDOUT/STDERR contents to a variable
by lothos (Novice) on Sep 25, 2009 at 22:57 UTC

    Good stuff. Doesn't seem to work for my eval though..

    print "Script content: $script_content\n"; print "Script input: $script_input\n"; open(SAVEOUT, ">&STDOUT"); open(SAVEERR, ">&STDERR"); close(STDIN); open(STDIN, '<',\my $stdin); #seek STDIN,0,0; # with or without, no diff. $stdin .= $script_input; #seek STDIN,0,0; # with or without, no diff. close(STDOUT); open(STDOUT,'>' , \my $stdout); close(STDERR); open(STDERR,'>' , \my $stderr); select(STDERR); $| = 1; select(STDOUT); $| = 1; eval $script_content; my $result_code = $@; close(STDOUT); close(STDERR); open(STDOUT, ">&SAVEOUT"); open(STDERR, ">&SAVEERR"); if ( ! $stderr ) { $stderr = ''; } # my db doesn't like nulls. if ( ! $stdout ) { $stdout = ''; } print "STDERR:" . $stderr; print "STDOUT:" . $stdout;

    In all variations where I'm using STDIN that is tied to a variable, I still get the manpage. Argh.

    I'm thinking the difference is that in your scenario you can do your writes to STDIN after the process has it. I think I have to have it set up prior to my eval, or my read of stdin within my evaled script will just return as it would get EOF immediately.