1

我正在尝试使用 select 更改系统函数的标准输出。但它似乎不起作用。系统输出显示在控制台上,而不是重定向到文件。

use strict;
use warnings;

chdir "C:\\Documents and Settings\\" or die "cannot open the dir\n";
open FH, ">out.txt" or die "cannot open out.txt\n";
select FH or die " cannot change the stdout\n";
system "dir /a" ; 

虽然我可以system "dir /a > out.txt",但我想知道为什么上面的代码不起作用。

4

5 回答 5

3

select函数更改输出的默认文件句柄。它不会更改 STDOUT,无论它是否是输出的默认文件句柄,它都指向它所指向的任何内容。如果要更改 STDOUT,则必须执行 ylebre 或 Jon's answer 之类的操作。

当您启动子进程时,它会获得与父进程相同的标准输出。它并不关心父级的默认文件句柄是什么。

于 2009-06-13T21:31:52.507 回答
2

您的代码的问题是该system命令没有为您捕获输出。您可以使用qx//

use strict;
use warnings;

open my $fh, ">", "output.txt" or die $!;
my $oldfh= select $fh;
print qx/ls -a/;
select $oldfh;
close $fh or warn $!;

还有其他选项可以运行外部应用程序并读取它的输出,例如IPC::Open2IPC::Open3模块。它们默认包含在 perl 中。

附注:不要将 glob 用于文件句柄:它们是全局变量,而全局变量是邪恶的。改用词法变量(FHvs. $fh)。此外,您应该使用三个参数open而不是两个参数,因为前者比后者更安全。

于 2009-06-13T16:14:56.467 回答
1

在这种情况下,我不确定“选择”是您要寻找的。要将 STDOUT 重定向到文件,您可以执行以下操作:

use strict;
use warnings;
use IO::Handle;
open FH, "> out.txt";
STDOUT->fdopen( \*FH, 'w' ) or die $!;
print "Hello world!\n";
system "dir /a";

希望这可以帮助!

于 2009-06-13T15:58:02.887 回答
1

也许有帮助

于 2009-06-13T16:08:07.543 回答
-2

我在系统(不是 Perl)级别重新分配文件描述符:

    sub reopen($$$) {
        open $_[0], $_[1]. '&='. fileno($_[2]) or die "failed to reopen: $!";
    }

    reopen *STDOUT,  '>', $new_stdout_handle;

现在任何你 fork 的东西都会认为 $new_stdout_handle 是标准输出。

我粘贴了一个完整的例子来概括:http: //gist.github.com/129407

于 2009-06-13T19:48:49.057 回答