簡體   English   中英

STDOUT重定向到變量不捕獲管道輸出

[英]STDOUT redirected to variable not catching pipe output

我想暫時將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
4

你在mob的答案中有一個詳細的解釋,為什么你不能將孩子的STDOUT重定向到一個變量,這實際上不是一個文件句柄。

相反,您可以使用模塊運行外部程序,這可以將標准流重定向到變量。 然后,您可以根據需要將字符串與重定向輸出組合在一起。

IPC :: Run3的一個例子

use warnings;
use strict;
use feature 'say';

use IPC::Run3;

open my $fh, ">", \my $so_1;     
my $old = select $fh;         # make $fh the default for output,
say "To select-ed default";   # so prints end up in $so_1

run3 ["ls", "-l", "./"], undef, \my $so_2;   # output goes to $so_2

select $old;                  # restore STDOUT as default for output
print $so_1, $so_2;

在這里,我使用select來操作默認打印的位置(沒有指定文件句柄)。

請注意,例如重定向run3在不同的變量( $so_2 ),比使用以前的重定向的一個。 如果您更願意附加到同一個變量,請在%options指定

run3 ["ls", "-l", "./"], undef, \$so_1, { append_stdout => 1 };

並從打印語句中刪除$so_2

該模塊使用臨時文件進行此重定向,正如回答中也指出的那樣。

其他一些選項是Capture :: Tiny ,可以從幾乎任何代碼重定向輸出,具有簡單而干凈的界面,以及非常強大,圓潤,更復雜的IPC :: Run

這是不可能的。

管道打開和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

管道打開並且系統調用將無法寫入此文件句柄。

您將需要更復雜的解決方法,例如將管道打開輸出寫入文件,然后將該文件復制到內存中變量中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM