Как я могу изменить стандартный дескриптор выходного файла для системного вызова в Perl?

StackOverflow https://stackoverflow.com/questions/990913

  •  13-09-2019
  •  | 
  •  

Вопрос

Я пытаюсь изменить стандартный вывод системной функции с помощью 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", Я хочу знать, почему приведенный выше код не работает.

Это было полезно?

Решение

Тот самый select функция изменяет дескриптор файла по умолчанию для вывода.Это не изменяет стандартный вывод, который указывает на то, на что он указывает, независимо от того, является ли это дескриптором файла по умолчанию для вывода.Если вы хотите изменить стандартный вывод, вы должны сделать что-то вроде ylebre или Jon's answer.

Когда вы запускаете дочерний процесс, он получает тот же стандартный вывод, что и родительский.Однако не имеет значения, какой дескриптор файла по умолчанию используется у родительского файла.

Другие советы

Проблема с вашим кодом в том, что 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::Open2 и IPC::Open3 модули.Они включены в Perl по умолчанию.

Примечание:не используйте globs для дескрипторов файлов:они глобалы, а глобалы — это зло.Вместо этого используйте лексические переменные (FH против. $fh).Кроме того, вы должны использовать три аргумента open вместо двух параметров, так как первый безопаснее второго.

Может быть этот помогает

Я не уверен, что «выбрать» — это то, что вы ищете в этом случае.Чтобы перенаправить 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";

Надеюсь это поможет!

Я переназначаю файловые дескрипторы на системном (не Perl) уровне:

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

    reopen *STDOUT,  '>', $new_stdout_handle;

Теперь все, что вы создадите, будет считать, что $new_stdout_handle является стандартным выводом.

Я вставил полный пример в суть: http://gist.github.com/129407

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top