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

Yep. That works for STDOUT/STDERR. Same thing for STDIN?
my $stdin = 'Some input text here'; open(STDIN,'<', \$stdin);

That give about 10 pages of errors that look like a manpage for PerlIO.

Thank you,

Replies are listed 'Best First'.
Re^3: Reassign STDOUT/STDERR contents to a variable
by almut (Canon) on Sep 25, 2009 at 18:12 UTC

    Should work, too, in principle, e.g.

    my $stdin = "Some input text here\n"; close STDIN; open(STDIN,'<', \$stdin) or die $!; while (my $line = <STDIN>) { print "got line: $line"; } __END__ got line: Some input text here

    What are those 10 pages complaining about? :)

      Yep. Your test code works, but in my script I get this. Ignore the Host not found: on the lines. That's output from my script. Looks like a perlio man page.

      I also failed to mention that the input I'm speaking of might, or might not be binmode. This works as expected:

      open(FILE,'>' . $stdin_file); binmode(FILE); print FILE $script_input; close(FILE); close(STDIN); open(STDIN, '<',$stdin_file);
      This:
      #open(FILE,'>' . $stdin_file); #binmode(FILE); #print FILE $script_input; #close(FILE); close(STDIN); open(STDIN, '<',\$script_input);
      Results in my output being:

        Sorry, I haven't got the foggiest what's going on in your case :)  Honestly. I can't replicate anything similar here.

        binmode should not matter, AFAICT.  Do you get any errors when you add ... or die $! to the various open statements?

Re^3: Reassign STDOUT/STDERR contents to a variable
by bv (Friar) on Sep 25, 2009 at 20:23 UTC

    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)))

      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.

Re^3: Reassign STDOUT/STDERR contents to a variable
by bv (Friar) on Sep 25, 2009 at 18:37 UTC

    You need to close STDIN first (same goes for STDOUT and STDERR). Then reopen to wherever.

    print pack("A25",pack("V*",map{1919242272+$_}(34481450,-49737472,6228,0,-285028276,6979,-1380265972)))
      yeah. I do. I just missed it in the 'making it brief' copy. I'm copying from a 400 line script with all sorts of nasty other stuff. Thanks,