我想暂时将stdout重定向到内存变量。 打印正确地重定向到我的变量但不是管道的输出(在我的示例中为bc)。 到底是怎么回事?
#!/usr/bin/perl my $stdout_sink; open(my $orig_stdout, ">&STDOUT") || die $!; close STDOUT; open(STDOUT, ">", \$stdout_sink) || die $!; # produce some output in different ways print "before bc\n"; # ok open my $fh, "| bc"; print $fh "2+2\n"; # not ok close $fh; close STDOUT; open(STDOUT, ">&", $orig_stdout) || die $!; print "$stdout_sink";实际输出将是:
before bc预期产量:
before bc 4I want to temporarily redirect stdout to an in memory variable. Prints are correctly redirected to my variable but not the output of a pipe (bc in my example). What is going on?
#!/usr/bin/perl my $stdout_sink; open(my $orig_stdout, ">&STDOUT") || die $!; close STDOUT; open(STDOUT, ">", \$stdout_sink) || die $!; # produce some output in different ways print "before bc\n"; # ok open my $fh, "| bc"; print $fh "2+2\n"; # not ok close $fh; close STDOUT; open(STDOUT, ">&", $orig_stdout) || die $!; print "$stdout_sink";Actual ouput will be:
before bcExpected output:
before bc 4最满意答案
这不可能。
管道打开和system调用的标准输出被写入文件描述符1.通常,Perl的STDOUT文件句柄与文件描述符1相关联,但可以对其进行操作。
在此示例中, system调用写入STDOUT文件句柄,该文件句柄写入文件foo 。
close STDOUT; # closes file descriptor 1 open STDOUT, '>', 'foo'; # reopens STDOUT as file descriptor 1 system("echo bar"); close STDOUT; print STDERR "foo: ",`cat foo`; # result: "foo: bar"但在此示例中, system调用写入BAZ文件句柄。
close STDOUT; # closes file descriptor 1 open BAZ, '>', 'baz'; # attaches fd 1 to handle BAZ open STDOUT, '>', 'foo'; # opens new file descriptor, maybe fd 3 system("echo bar"); close STDOUT; print STDERR "foo: ",`cat foo`; print STDERR "baz: ",`cat baz`; # result: "foo: baz: bar"内存中的文件句柄不是真正的文件句柄。 如果您在其上调用fileno ,您将(通常可能依赖于操作系统)获得负数。
open STDOUT, '>', \$scalar; print STDERR fileno(STDOUT); # -1管道打开并且系统调用将无法写入此文件句柄。
您将需要更复杂的解决方法,例如将管道打开输出写入文件,然后将该文件复制到内存中变量中。
This is ... not possible.
Standard output of piped opens and system calls are written to file descriptor 1. Normally, Perl's STDOUT file handle is associated with file descriptor 1, but that can be manipulated.
In this example, the system calls writes to STDOUT filehandle, which writes to the file foo.
close STDOUT; # closes file descriptor 1 open STDOUT, '>', 'foo'; # reopens STDOUT as file descriptor 1 system("echo bar"); close STDOUT; print STDERR "foo: ",`cat foo`; # result: "foo: bar"But in this example, the system calls writes to the BAZ filehandle.
close STDOUT; # closes file descriptor 1 open BAZ, '>', 'baz'; # attaches fd 1 to handle BAZ open STDOUT, '>', 'foo'; # opens new file descriptor, maybe fd 3 system("echo bar"); close STDOUT; print STDERR "foo: ",`cat foo`; print STDERR "baz: ",`cat baz`; # result: "foo: baz: bar"An in-memory filehandle is not a real filehandle. If you call fileno on it, you will (generally, may be OS dependent) get a negative number.
open STDOUT, '>', \$scalar; print STDERR fileno(STDOUT); # -1Piped opens and system calls will not be able to write to this filehandle.
You will need a more complicated workaround, like writing the piped open output to a file, and then copying that file into the in-memory variable.
更多推荐
发布评论