【发布时间】:2010-02-22 03:16:44
【问题描述】:
如果我有一个函数可能会传递一个文件名或各种文件句柄或 typeglob,该函数如何区分这些参数 - 包括区分*DATA 和*STDIN 之间的区别?
根据目前收到的答案更新了代码谢谢大家。
use strict;
use warnings;
use FileHandle;
sub file_thing_type {
my ($f) = shift;
my $type;
my $r = ref $f;
if ($r eq 'GLOB' or ref(\$f) eq 'GLOB'){
# Regular and built-in file handles.
my $fn = fileno $f;
if (defined $fn){
my %built_in = (
'STDIN' => fileno(*STDIN),
'STDOUT' => fileno(*STDOUT),
'STDERR' => fileno(*STDERR),
'DATA' => fileno(*DATA),
);
for my $k (keys %built_in){
if (defined $built_in{$k} and $built_in{$k} == $fn){
$type = $k;
last;
}
}
$type = 'regular file handle' unless defined $type;
}
else {
$type = 'non-IO glob';
}
}
elsif ($r){
# A reference of some kind.
$type = $r;
# Might be an IO object. Has it been opened?
{
no warnings 'unopened';
$type .= ' opened' if -f $f;
}
}
else {
# File name or just some other value?
$type = -f $f ? 'file name' : 'other';
}
return $type;
}
open(my $h, '<', $0) or die $!;
printf "%12s => %s\n",
$_->[0],
file_thing_type($_->[1])
for (
[ 'handle', $h ], # regular file handle
[ 'DATA', *DATA ], # DATA if source has DATA section; else non-IO glob
[ 'STDIN', *STDIN ], # STDIN
[ 'STDOUT', *STDOUT ], # STDOUT
[ 'STDERR', *STDERR ], # STDERR
[ 'FOO', *FOO, *FOO ], # non-IO glob
[ 'FileHandle', FileHandle->new ], # FileHandle
[ 'FileHandle', FileHandle->new($0) ], # FileHandle opened
[ 'file name', $0 ], # file name
[ 'not file', '' ], # other
[ 'misc', {bar=>1} ], # HASH
);
__END__
【问题讨论】:
-
它们都是文件句柄。你到底想测试什么?您可以在句柄上使用“-t”测试来检查它是否来自/去往终端 (TTY),这对于 STDIN 和 STDOUT 通常是正确的,除非通过管道传输。
-
请让我们知道您想要做的更广泛的背景。为什么需要能够区分
DATA和STDIN? -
@gbacon 老实说,我不确定。我昨晚深夜在做一些事情,并认为这可能有助于区分。然后我注意到 Data::Dumper 能够将它们区分开来(有点),所以我认为这个问题可能有一个简单的答案,所以我提出了它。从那时起,我对我的项目的想法发生了变化,所以现在我们只是出于好奇。 :)
标签: perl filehandle typeglob