Perl子例程如何区分文件名,文件handes,* DATA和* STDIN?

时间:2010-02-22 03:16:45

标签: perl filehandle typeglob

如果我有一个可能传递文件名或各种文件句柄或typeglobs的函数,那么函数如何区分这些参数 - 包括告诉差异,例如*DATA和{{1 }}?

根据目前为止收到的答案更新了代码谢谢大家。

*STDIN

3 个答案:

答案 0 :(得分:2)

更新:区分可能分配给*DATA*STDIN整数的变量的问题是fileno的工作:

sub data_or_stdin {
  my $x = shift;
  if (fileno($x) == fileno(DATA)) {
    return "DATA";
  } elsif (fileno($x) == fileno(STDIN)) {
    return "STDIN";
  } else {
    return "NEITHER";
  }
}

print "DATA:  ", data_or_stdin(*DATA), "\n";
print "STDIN: ", data_or_stdin(*STDIN), "\n";
open(ZZZ, ">>", "zzz"); close ZZZ;
open(ZZZ, "<", "zzz"); print "ZZZ: ", data_or_stdin(*ZZZ), "\n"; close ZZZ;
open($fh, "<", "zzz"); print "\$fh=ZZZ: ", data_or_stdin($fh), "\n"; close $fh;
$fh = *DATA; print "\$fh=DATA: ", data_or_stdin($fh), "\n";
$fh = *STDIN; print "\$fh=STDIN: ", data_or_stdin($fh), "\n";

__END__
stuff;
$ perl data_or_stdin.pl
DATA:  DATA
STDIN: DATA
ZZZ: NEITHER
$fh=ZZZ: NEITHER
$fh=DATA: DATA
$fh=STDIN: DATA

如果$f是文件句柄,则ref $fref \$f将为"GLOB" 如果$f是标量,则ref \$f将为"SCALAR"

sub filehandle_or_scalar {
  my $x = shift;
  if (ref $x eq "GLOB" || ref \$x eq "GLOB") {
      return "filehandle";
  } elsif (ref \$x eq "SCALAR") {
      return "scalar";
  } else {
      return "not filehandle or scalar";
  }
}

print "STDIN: ", filehandle_or_scalar(*STDIN), "\n";
print "\$_: ", filehandle_or_scalar($_), "\n";
open($fh, ">", "zzz");
print "\$fh: ", filehandle_or_scalar($fh), "\n";
print "string: ", filehandle_or_scalar('file.txt'), "\n";
print "ref: ", filehandle_or_scalar(\$x), "\n"

###########################################

$ perl filehandle_or_scalar.pl
STDIN: filehandle
$_: scalar
$fh: filehandle
string: scalar
ref: not filehandle or scalar

答案 1 :(得分:1)

您可以在字符串文件句柄上使用模式匹配* STDIN,* DATA等...

if ($f =~ /\bSTDIN$/) {
    return "STDIN";
} elsif ($f =~ /\bDATA$/) {
    return "DATA";
}

哈基,但可能就够了......

答案 2 :(得分:1)

mobrule的方法看起来很有希望:

perl -E 'open $fh, "<", "/dev/null"; say ref $fh;'

将输出GLOB。但是,

也是如此
perl -E 'say ref \*FOO;'

“真正的”文件句柄也将具有与之关联的文件描述符 您可以使用fileno确定它:

perl -MData::Dumper -E 'open $fh, "<", "/dev/null"; say Data::Dumper::Dumper([fileno $fh, fileno \*STDIN, fileno \*FOO])'

将输出如下内容:

$VAR1 = [
          3,
          0,
          undef
        ];

您可以使用它来告诉正在用于文件I / O的GLOB 一个不是。在UNIX系统上,标准输入流按照惯例与文件描述符0 相关联。

我想到的另一件事是一个与a相关的类 文件句柄。这些需要实现您的特定接口 可以测试使用can。请参阅平局VARIABLE,CLASSNAME,LIST 有关此界面的详细信息,请参阅 perlfunc