Подтвердить что ты не робот

Как я могу указать дескриптор файла в STDOUT (или другую файловую ручку) в Perl?

Я хочу сделать быстрый script, который записывает в файл, если файл указан, или stdout, если файл не указан. Мне было бы намного легче сделать это, если бы я мог запустить script, указав новый дескриптор файла OUTFILE на то, что из этого подходит.

Я знаю, что могу выполнить то, что хочу, просто указывая STDOUT на мой выходной файл, когда это уместно, но я бы предпочел не делать этого, поскольку я не хочу путать кого-либо, использующего script позже, и задаюсь вопросом, почему их печать заявления не работают. Кроме того, я по-прежнему хотел бы использовать случайный запрос печати самостоятельно для устранения неполадок и никогда не хочу, чтобы эта печать выводилась.

Все это говорит о том, что я ищу, что-то вроде: open( OUTFILE, ($output ? ">$output" : STDOUT );
кроме того, что не работает.

Идеи?

4b9b3361

Ответ 1

Некоторые способы (глобусы):

# Requires 2-arg open, unfortunately
open(OUTPUT, "> ".($output || '-'))  or die;

if ($output) {
   open(OUTPUT, '>', $output) or die;
} else {
   *OUTPUT = *STDOUT;
}

if ($output) {
   open(OUTPUT, '>', $output) or die;
} else {
   open(OUTPUT, '>&', \*STDOUT) or die;
}

Некоторые способы (лексический var):

# Requires 2-arg open, unfortunately
open(my $fh, "> ".($output || '-'))  or die;

my $fh;
if ($output) {
   open($fh, '>', $output) or die;
} else {
   $fh = \*STDOUT;
}

my $fh;
if ($output) {
   open($fh, '>', $output) or die;
} else {
   open($fh, '>&', \*STDOUT) or die;
}

Некоторые способы (другие):

# Changes the default handle for <print "foo">.
if ($output) {
   open(OUTPUT, '>', $output) or die;
   select(OUTPUT);
}

Ответ 2

Для читателя (поскольку OP уже "получил работу" ):

В документации Perl "perlopentut" (perldoc perlopentut) приводятся примеры открытия альтернативного дескриптора файла, направленного на STDOUT, но он использует дескрипторы дескриптора файла и версию с двумя аргументами open, обе из которых несколько древние. Книга Damian Conway "Perl Best Practices" (а также Perl:: Critic, которая основана на книге Дамиана) подчеркивает использование трех открытий arg и лексических дескрипторов файлов (my $foo дескрипторов файла стиля). хроматический "Modern Perl" также вкратце упоминает использование лексических дескрипторов файлов и, в случае необходимости, отпугивает слова. Три arg open считаются более безопасными, поскольку он ограничивает воздействие на инъекции оболочки. В то время как конкретный случай здесь имеет низкий риск, он по-прежнему является хорошей привычкой по умолчанию для трех-arg open.

Необходимо внимательно прочитать примеры, показанные в документации Perl open (perldoc -f open), и небольшую интерпретацию, чтобы заметить правильное размещение символа амперсанда при открытии дубликата filahandle, направленного на STDOUT при использовании версия с тремя аргументами open. Можно ошибочно предположить, что это должно работать: open my $fh, '>', '&STDOUT' or die $!;, главным образом потому, что это выглядит как формат, который мы привыкли видеть (амперсанд и предшествующий имени символа). Но этот синтаксис не соответствует требованиям open, и мы привыкли видеть его в совершенно другом контексте: некоторые вызовы подпрограмм.

Правильный способ открыть обход для STDOUT с помощью трех arg open состоит в объединении > и & в один и тот же второй аргумент и оставить STDOUT голыми, например:

use Modern::Perl;

open my $fh, '>&', STDOUT or die "Bleah: $!";

say $fh 'Printing alternate filehandle "$fh" worked.';
say 'Implicitly printing to "STDOUT" also works.';

Или передайте STDOUT в open в качестве ссылки на типglob:

open my $fh, '>&', \*STDOUT or ...

Ответ 3

- - это магия. Следуйте за соглашением или нарушите принцип наименьшего удивления.

use autodie qw(:all);
use Getopt::Long qw(GetOptions);
GetOptions(\my %opt, 'out=s') or die 'usage';
die 'usage' unless $opt{out};
open my $handle, ">$opt{out}";

perl foo -o blahblah        # opens file blahblah for writing
perl foo -o -               # goes to STDOUT

Связано: Есть ли причины когда-либо использовать форму с двумя аргументами open (...) в Perl?

Ответ 4

Nevermind. Догадаться. Бросок в амперсанд делает трюк. Полный рабочий код:
open( OUTPUT, ( $output ? ">$output" : ">&STDOUT" ) );

Ответ 5

Вы всегда можете просто написать регулярный вывод в STDOUT, а операторы отладки - STDERR. Затем, если пользователь хочет, чтобы выход пошел в файл, он может просто перенаправить STDOUT в файл в командной строке.