2014-12-15 3 views
1

для программы, которую я пытаюсь написать в perl прямо сейчас, я хочу построить опцию, которая выводит вывод в выходной файл, что довольно легко с Perl-модулем Getopt. однако, если опция не используется, я хотел бы, чтобы выход перешел на терминал (STDOUT). для этого я написал небольшой скрипт, чтобы проверить, могу ли я построить коммутатор с модулем IO :: File.ищет простой переключатель между «write to STDOUT» и «write to outfile»

#!/usr/bin/env perl 
use strict; 
use warnings; 
use Getopt::Long; 
use IO::File; 

my $outfilename; 

GetOptions (
    "out=s" => \$outfilename, 
); 

my $out = IO::File->new(">$outfilename"); 

if (defined $out) { 
    print $out "Hello World!\n"; 
} 
else { 
    print "Hello World!\n"; 
} 

close $out if $outfilename; 

хотя программа «прогонов» с или без опции -o, когда я запустить его без -o, Perl говорит мне, что $ outfilename в строке 13 не инициализирована, который я предполагаю, потому что Getopt возвращает переменные как «false», когда опция не используется. однако, я не могу придумать способ обойти это. Можете ли вы, ребята, помочь мне?
также, я абсолютно уверен, что есть гораздо более простой способ построить такой коммутатор, о котором я не знаю. я просто писал это, потому что я не мог найти лучшего способа в Интернете, поэтому, если у вас есть какие-то советы о том, как сделать это умнее, я был бы очень благодарен!

+0

Я не знаю, знаете ли вы это, потому что я видел, что вы пытаетесь принять более одного ответа, но вы можете выбрать только один ответ на свой вопрос. – TLP

+0

да: D я просто понял, что, и мне это не нравится, потому что я думаю, что все ансеры очень полезны здесь. – Prawn

+0

Да, ответы в теге Perl, как правило, имеют высокое качество, и, как вы можете видеть, он также активно рассматривается, как можно заметить в нашей дискуссии в комментариях. Я бы сказал, что «лучшее» решение, вероятно, является первым икегами. Не из-за причин, о которых он заявляет, а потому, что он более прозрачен: 'print $ outfh" stuff "' явно говорит кому-то, кто читает код, что происходит, тогда как 'print 'stuff'' может ввести в заблуждение. – TLP

ответ

4

Вы получаете предупреждение, потому что вы используете $outfilename в качестве имени файла безусловно, даже если он имеет только значение, когда --out было предусмотрено.

Не помещайте весь print в if. Если вы это сделаете, вы получите много дублированного кода. Либо создать дескриптор файла, который инициализирован при любых условиях

my $outfh; 
if (defined($outfilename)) { 
    open($outfh, '>', $outfilename) 
     or die($!); 
} else { 
    $outfh = \*STDOUT; 
} 

print $outfh "Hello World!\n"; 

или перенаправить STDOUT

if (defined($outfilename)) { 
    open(STDOUT, '>', $outfilename) 
     or die($!); 
} 

print "Hello World!\n"; 

Но почему вы не перенаправление STDOUT с внешней стороны?

script >script.log 
+1

Или используйте 'select' для установки дескриптора выходного файла. – TLP

+0

@TLP, я не согласен. Нет никаких признаков того, что существует необходимость в выборе и выборе проблем. – ikegami

+0

Ох ... бог, большое спасибо, это хорошо знать! поэтому IO :: File на самом деле не нужен или даже «на пути» здесь? также, как бы вы закрыли этот файл, учитывая, что он открыт только при определенном условии? я спрашиваю, потому что для реальной программы файлы, которые он собирается создать, довольно большие, и я хотел бы облегчить рабочее пространство всякий раз, когда смогу. – Prawn

0

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

if($outfilename) { 
    open my $of, ">", $outfilename; 
    *STDOUT = $of; 
} 

print "Hello World!\n"; 
+0

Или вы можете просто «выбрать $ of», не требуя уничтожения стандартного дескриптора вывода. – TLP

+0

Оба этих решения (назначая '* STDOUT' и' select') будут разбиваться в некоторых условиях (например, выход детей не будет перенаправлен). Мое решение перенаправляет fd1, поэтому у него нет этих проблем. – ikegami

4

Вы можете использовать select для установки выходного файла по умолчанию дескриптор с. Это приведет к тому, что print автоматически распечатает дескриптор файла select.

if ($outfilename) { 
    open my $outfh, ">", $outfilename 
     or die "Cannot open $outfilename for output: $!"; 
    select $outfh; 
} 

print "Hello world!\n"; 
+0

Это сломается под некоторыми условия (например, выход детей не будет перенаправлен). Мое решение перенаправляет fd1, поэтому у него нет этих проблем. – ikegami

+0

Значит, вы говорите, что 'select' никогда не должен использоваться? – TLP

+0

Нет. Я просто говорю, что нет никаких указаний на то, что есть необходимость в выборе и выборе проблем. – ikegami

-1

Вы бы лучше взглянуть на следующем:

select вызова позволяет переопределить, что по умолчанию файл обработчик для print звонки. SelectSaver позволяет делать то же самое в области заданного блока кода.

В вашем случае вы можете переписать свой код, чтобы при необходимости создать дескриптор выходного файла, и select, прежде чем запускать код, который будет выполнять вывод. Код вывода, в свою очередь, просто вызовет print без дескриптора файла.

+0

Просьба пояснить нижний предел – fjardon

+0

Это сломается при некоторых условиях (например, выход детей не будет перенаправлен). Мое решение перенаправляет fd1, поэтому у него нет этих проблем. – ikegami

+0

@ikegami Помог ли OP говорить о детском процессе? НЕТ! Вы отвечаете на вопрос, который не задан. Пожалуйста, соблюдайте правила. – fjardon

 Смежные вопросы

  • Нет связанных вопросов^_^