我正在尝试创建一些可以协同工作的函数。 getFH
应该采用模式打开文件(>
或<
),然后是文件本身(从命令行)。它应该做一些检查,看看文件是否可以打开,然后打开它,并返回文件句柄。 doSomething
应该接受文件句柄,并循环数据并执行任何操作。但是当程序排到while循环时,我收到错误:
未打开的文件句柄1上的readline()
我在这里做错了什么?
#! /usr/bin/perl
use warnings;
use strict;
use feature qw(say);
use Getopt::Long;
use Pod::Usage;
# command line param(s)
my $infile = '';
my $usage = "\n\n$0 [options] \n
Options
-infile Infile
-help Show this help message
\n";
# check flags
GetOptions(
'infile=s' => \$infile,
help => sub { pod2usage($usage) },
) or pod2usage(2);
my $inFH = getFh('<', $infile);
doSomething($inFH);
## Subroutines ##
## getFH ##
## @params:
## How to open file: '<' or '>'
## File to open
sub getFh {
my ($read_or_write, $file) = @_;
my $fh;
if ( ! defined $read_or_write ) {
die "Read or Write symbol not provided", $!;
}
if ( ! defined $file ) {
die "File not provided", $!;
}
unless ( -e -f -r -w $file ) {
die "File $file not suitable to use", $!;
}
unless ( open( $fh, $read_or_write, $file ) ) {
die "Cannot open $file",$!;
}
return($fh);
}
#Take in filehandle and do something with data
sub doSomething{
my $fh = @_;
while ( <$fh> ) {
say $_;
}
}
答案 0 :(得分:3)
my $fh = @_;
这一行并不代表您认为的含义。它将$fh
设置为 @_
中的项目数而不是传入的文件句柄 - 如果您打印$fh
的值,它将为{ {1}}而不是文件句柄。
改为使用1
,my $fh = shift
或my $fh = $_[0]
。
答案 1 :(得分:2)
正如已经指出的那样,my $fh = @_
会将$fh
设置为1,这不是文件句柄。使用
my ($fh) = @_
而是使用列表分配
另外
-e -f -r -w $file
将无法满足您的需求。你需要
-e $file and -f $file and -r $file and -w $file
通过使用下划线_
代替文件名,您可以使其更简洁有效,这将重新使用为先前文件测试获取的信息
-e $file and -f _ and -r _ and -w _
但是,请注意,如果文件不是可写,您将拒绝请求,如果请求是打开文件进行读取,则无效。此外,如果文件不存在,-f
将返回 false ,因此-e
是多余的
最好在$!
字符串中加入die
,因为它包含失败的原因,但您的前两个测试不适用设置此值,因此应该只是die "Read or Write symbol not provided";
等。
此外,die "Cannot open $file", $!
应该是
die qq{Cannot open "$file": $!}
清楚地说明文件名是否为空,并在消息和值$!
之间添加一些空格
从文件中读取的行最后会有换行符,因此不需要say
。只需print while <$fh>
就可以了
Perl变量名通常是 snake_case ,因此get_fh
和do_something
更常见