使用选择返回的文件句柄

时间:2018-10-15 14:35:02

标签: perl

我正在使用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的返回值中获得可用的文件句柄?

P.S。我需要将此文件句柄作为OutputFile传递给XML :: Simple的XMLout()。

3 个答案:

答案 0 :(得分:3)

select的要点是您根本不需要指定手柄,因为它是默认手柄。

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

这也是不推荐使用select的原因:它引入了难以跟踪和调试的全局状态。

答案 1 :(得分:3)

只需使用

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作为文件句柄接受四件事:

  • 对IO对象的引用。

    >perl -e"my $fh = *STDOUT{IO}; CORE::say($fh 'foo');"
    foo
    
  • 一个包含对IO对象的引用的glob。

    >perl -e"my $fh = *STDOUT; CORE::say($fh 'foo');"
    foo
    
  • 对glob的引用,其中包含对IO对象的引用。

    >perl -e"my $fh = \*STDOUT; CORE::say($fh 'foo');"
    foo
    
  • 对glob的“符号引用”,其中包含对IO对象的引用。

    >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的速度要差一百万倍。参见Why is XML::Simple Discouraged?

如果要修改XML,请考虑XML::LibXMLXML::Twig

如果要生成XML,请考虑XML::Writer

答案 2 :(得分:0)

首先,您不应该使用XML :: Simple,因为它将需要大量工作来确保您的输出将生成一致的XML。至少确保您使用的是适当的ForceArray参数。

为什么不使用文件处理恶作剧,为什么不使用更简单的

print XMLout($data, %options);

...而不是尝试传递默认文件句柄?

相关问题