используя дескриптор файла, возвращаемый select - PullRequest
0 голосов
/ 15 октября 2018

Я вытаскиваю волосы, используя дескриптор файла, возвращенный select.

Документация о избранных читает:

  • select
    Возвращает текущий выбранный дескриптор файла.

У меня есть фрагмент кода, который печатает некоторые данные и обычно выполняется без какого-либо перенаправления.Но есть один вариант использования, где select используется для перенаправления вывода на печать в файл.

В этом фрагменте кода мне нужно использовать текущий дескриптор выбранного файла.Я попробовал следующий фрагмент кода:

my $fh = select;
print $fh "test\n";

Я написал короткую тестовую программу, чтобы продемонстрировать свою проблему:

#!/usr/bin/perl

use strict;
use warnings;

sub test
{
  my $fh=select;
  print $fh "@_\n";
}

my $oldfh;

# this works :-)
open my $test1, "> test1.txt";
$oldfh = select $test1;
test("test1");
close select $oldfh if defined $oldfh;

#this doesn't work. :-(
# Can't use string ("main::TEST2") as a symbol ref while "strict refs" in use
open TEST2,">test2.txt";
$oldfh = select TEST2;
test("test2");
close select $oldfh if defined $oldfh;

#this doesn't work, too. :-(
# gives Can't use string ("main::STDOUT") as a symbol ref while "strict refs" in use at
test("test");

Кажется, что select не возвращает ссылку на дескриптор файлано строка, содержащая имя дескриптора файла.

Что мне нужно сделать, чтобы всегда получить пригодный для использования дескриптор файла из возвращаемого значения select?

PS Мне нужно передать этот дескриптор файла какВыходной файл в XML :: Simple XMLout ().

Ответы [ 3 ]

0 голосов
/ 15 октября 2018

Прежде всего, вы не должны использовать XML :: Simple, потому что потребуется много работы, чтобы убедиться, что ваш вывод будет генерировать согласованный XML.По крайней мере, убедитесь, что вы используете соответствующие параметры ForceArray.

Вместо того, чтобы делать махинации с файловыми дескрипторами, почему бы вам не использовать более простой

print XMLout($data, %options);

... вместо попыткипередать файловый дескриптор по умолчанию?

0 голосов
/ 15 октября 2018

Просто используйте

print XMLout(...); 

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

Он действительно может возвращать обычную обычную строку.

>perl -MDevel::Peek -E"Dump(select())"
SV = PV(0x6cbe38) at 0x260e850
  REFCNT = 1
  FLAGS = (PADTMP,POK,pPOK)
  PV = 0x261ce48 "main::STDOUT"\0
  CUR = 12
  LEN = 24

Но это совершенно приемлемо в качестве дескриптора файла для Perl.Perl принимает четыре дескриптора файла:

  • Ссылка на объект ввода-вывода.

    >perl -e"my $fh = *STDOUT{IO}; CORE::say($fh 'foo');"
    foo
    
  • Глобус, содержащийссылка на объект ввода-вывода.

    >perl -e"my $fh = *STDOUT; CORE::say($fh 'foo');"
    foo
    
  • ссылка на глобус, содержащий ссылку на объект ввода-вывода.

    >perl -e"my $fh = \*STDOUT; CORE::say($fh 'foo');"
    foo
    
  • «Символическая ссылка» на глобус, который содержит ссылку на объект ввода-вывода.

    >perl -e"my $fh = 'STDOUT'; CORE::say($fh 'foo');"
    foo
    

    Однако этот тип не работает под строгими ссылками.

    >perl -Mstrict -e"my $fh = 'STDOUT'; CORE::say($fh 'foo');"
    Can't use string ("STDOUT") as a symbol ref while "strict refs" in use at -e line 1.
    

Что мне нужно сделать, чтобы всегда получить пригодный для использования дескриптор файла из возвращаемого значения select?

Как показано выше, он уже возвращает идеально используемый файлсправиться.Если XMLout не поддерживает это, то это ошибка в XMLout.Вы можете обойти это следующим образом:

my $fh = select();
if (!ref($fh) && ref(\$fh) ne 'GLOB') {
   no strict qw( refs );
   $fh = \*$fh;
}

Это также можно использовать, чтобы сделать дескриптор пригодным для использования в строгой среде


Так плохо, как XML :: Simple при чтенииXML в миллион раз хуже при его создании.См. Почему XML :: Simple не рекомендуется? .

Рассмотрите XML :: LibXML или XML :: Twig , если вы изменяете XML.

Рассмотрим XML :: Writer , если вы генерируете XML.

0 голосов
/ 15 октября 2018

Точка select заключается в том, что вам вообще не нужно указывать дескриптор, поскольку он используется по умолчанию.

sub test {
    print "@_\n";
}

Это также причина, по которой select isnне рекомендуется: он вводит глобальное состояние, которое трудно отследить и отладить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...