Perl STDIN语法

时间:2014-04-04 19:42:49

标签: perl io

我已经遇到两种不同的语法来读取STDIN的输入,但是我无法弄清楚两者之间是否存在差异。

我介绍的第一种方法是:

$IN = Bio::SeqIO->new(-fh => *STDIN{IO}, '-format' => 'fasta', '-alphabet' => $moltype);

稍后在询问有关BioPerl IRC的一些问题后,我被告知这样写:

$IN = Bio::SeqIO->new(-fh => \*STDIN, '-format' => 'fasta', '-alphabet' => $moltype);

2 个答案:

答案 0 :(得分:3)

*STDIN{IO}将返回对IO对象的引用。

$ perl -MDevel::Peek -e'Dump(*STDIN{IO})'
SV = IV(0x166b988) at 0x166b998
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0x1688fe0
  SV = PVIO(0x168b5f0) at 0x1688fe0
    ...

\*STDIN将返回对包含IO对象的glob的引用。

$ perl -MDevel::Peek -e'Dump(\*STDIN)'
SV = IV(0xf5f988) at 0xf5f998
  REFCNT = 1
  FLAGS = (TEMP,ROK)
  RV = 0xf7cfc8
  SV = PVGV(0xf749b0) at 0xf7cfc8
     ...

所有Perl内置函数都可以处理 [1] ,但后者应该得到XS模块 [2] 的更好支持,因为它是open $fh, ...所放置的标量。

$ perl -MDevel::Peek -e'open(my $fh, "<", "/dev/null") or die; Dump($fh);'
SV = IV(0x144a518) at 0x144a528
  REFCNT = 1
  FLAGS = (PADMY,ROK)
  RV = 0x142c998
  SV = PVGV(0x1485c80) at 0x142c998
     ...

  1. 他们也可以直接处理glob(例如*STDIN)或符号名称作为字符串(例如"STDIN")。
  2. 用其他语言编写的模块。

答案 1 :(得分:1)

出于所有意图和目的,它们是等同的。您会更频繁地看到\*STDIN表单,而我更喜欢*STDIN{IO}

表单\*STDIN创建对“typeglob”的引用。 glob是Perl的包符号表中的一个条目。每个glob包含各种类型的引用 - glob *foo有一个哈希%foo,可以*foo{HASH}访问,一个数组@foo*foo{ARRAY},一个标量,格式,子例程和IO事物:*foo{IO}。如果不存在相应的变量,则可能未定义任何槽。

“IO thingy”将是任何当前Perl上->isa('IO::Handle')的对象。这是一个完整的对象与方法等。所以我们可以做

my $fh = *STDOUT{IO};
$fh->say("foo"); # you may need to "use IO::File" to actually load the methods

但为方便起见,STDOUT->say("foo")(裸字)和(\*STDOUT)->say("foo")(glob引用)也可以使用,但它们的类型不同。