Perl子例程如何区分文件名、文件句柄、*数据和*STDIN?
如果我有一个可以传递文件名或各种文件句柄或typeglobs的函数,那么该函数如何区分这些参数——包括告诉它们之间的区别,例如,Perl子例程如何区分文件名、文件句柄、*数据和*STDIN?,perl,filehandle,typeglob,Perl,Filehandle,Typeglob,如果我有一个可以传递文件名或各种文件句柄或typeglobs的函数,那么该函数如何区分这些参数——包括告诉它们之间的区别,例如,*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
*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__
使用严格;
使用警告;
使用文件句柄;
子文件类型{
我的($f)=班次;
我的$type;
my$r=ref$f;
如果($r均衡器‘GLOB’或参考(\$f)均衡器‘GLOB’){
#常规和内置文件句柄。
my$fn=fileno$f;
如果(定义为$fn){
我的内置%u=(
'STDIN'=>fileno(*STDIN),
'STDOUT'=>fileno(*STDOUT),
'STDERR'=>fileno(*STDERR),
“数据”=>fileno(*DATA),
);
对于我的$k(钥匙%内置){
if(定义为{$k}中的$build_和{$k}中的$build_==$fn){
$type=$k;
最后;
}
}
$type=‘常规文件句柄’,除非定义了$type;
}
否则{
$type='非IO全局';
}
}
elsif($r){
#某种参考资料。
$type=$r;
#可能是IO对象。它已打开吗?
{
没有“未打开”的警告;
$type.='opened'如果-f$f;
}
}
否则{
#文件名还是其他值?
$type=-f$f?“文件名”:“其他”;
}
返回$type;
}
open(my$h,更新:区分可能分配给*数据或*STDIN
全局的变量的问题是:
您可以对*STDIN、*DATA等的stringafied文件句柄使用模式匹配
if ($f =~ /\bSTDIN$/) {
return "STDIN";
} elsif ($f =~ /\bDATA$/) {
return "DATA";
}
有点老套,但可能已经足够了……mobrule的方法看起来很有希望:
perl -E 'open $fh, "<", "/dev/null"; say ref $fh;'
“真实”文件句柄还将有一个与
您可以使用fileno
确定它:
perl -MData::Dumper -E 'open $fh, "<", "/dev/null"; say Data::Dumper::Dumper([fileno $fh, fileno \*STDIN, fileno \*FOO])'
您可以使用它来告诉正在用于文件I/O的GLOB
在UNIX系统上,标准输入流按照惯例与文件描述符0关联
我想到的另一件事是一个与
这些需要实现一个特定的接口
可以测试是否使用can
。请参阅tie变量、CLASSNAME、LIST
perlfunc中的条目,了解有关此接口的详细信息。它们都是文件句柄。您到底想测试什么?您可以使用句柄上的“-t”测试来检查它是否来自/前往终端(TTY),这对于STDIN和STDOUT通常是正确的,除非是管道。请让我们知道您想要做什么的更广泛的背景。为什么您需要能够区分数据
和STDIN
?@gbacon老实说,我不确定。我昨晚很晚才在做一些事情,并认为它可能有助于区分guish。然后我注意到Data::Dumper能够将它们区分开来(某种程度上),所以我认为这个问题可能有一个简单的答案,于是我提出了这个问题。从那时起,我对我的项目的思考不断发展,所以现在我们只剩下好奇了。:)sub is_filehandle{应该是sub filehandle_或_scalar{
if ($f =~ /\bSTDIN$/) {
return "STDIN";
} elsif ($f =~ /\bDATA$/) {
return "DATA";
}
perl -E 'open $fh, "<", "/dev/null"; say ref $fh;'
perl -E 'say ref \*FOO;'
perl -MData::Dumper -E 'open $fh, "<", "/dev/null"; say Data::Dumper::Dumper([fileno $fh, fileno \*STDIN, fileno \*FOO])'
$VAR1 = [
3,
0,
undef
];