Return 来自子程序的文件句柄并传递给其他子程序
Return file handle from subroutine and pass to other subroutine
我正在尝试创建几个可以协同工作的函数。 getFH
应该采用打开文件的模式( >
或 <
),然后是文件本身(从命令行)。它应该做一些检查以查看文件是否可以打开,然后打开它,然后 return 文件句柄。 doSomething
应该接受文件句柄,循环数据并做任何事情。但是,当程序进入 while 循环时,出现错误:
readline() on unopened filehandle 1
我在这里做错了什么?
#! /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[=11=] [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 $_;
}
}
my $fh = @_;
这一行并不代表你认为的意思。它将 $fh
设置为 @_
中的项目数,而不是传入的文件句柄 - 如果您打印 $fh
的值,它将是 1
而不是文件句柄。
请改用 my $fh = shift
、my $fh = $_[0]
或 my ($fh) = @_
。
如前所述,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
将 return false,因此 -e
是多余的
最好在 die
字符串中包含 $!
,因为它包含失败的 原因,但您的第一个两个测试没有设置这个值,所以应该只是 die "Read or Write symbol not provided";
等
另外,die "Cannot open $file", $!
应该是
die qq{Cannot open "$file": $!}
明确文件名是否为空,并在消息和$!
的值之间添加一些space
从文件中读取的行最后会有一个换行符,所以不需要say
。只需 print while <$fh>
即可
Perl 变量名通常是snake_case,所以get_fh
和do_something
更常见
我正在尝试创建几个可以协同工作的函数。 getFH
应该采用打开文件的模式( >
或 <
),然后是文件本身(从命令行)。它应该做一些检查以查看文件是否可以打开,然后打开它,然后 return 文件句柄。 doSomething
应该接受文件句柄,循环数据并做任何事情。但是,当程序进入 while 循环时,出现错误:
readline() on unopened filehandle 1
我在这里做错了什么?
#! /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[=11=] [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 $_;
}
}
my $fh = @_;
这一行并不代表你认为的意思。它将 $fh
设置为 @_
中的项目数,而不是传入的文件句柄 - 如果您打印 $fh
的值,它将是 1
而不是文件句柄。
请改用 my $fh = shift
、my $fh = $_[0]
或 my ($fh) = @_
。
如前所述,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
将 return false,因此-e
是多余的最好在
die
字符串中包含$!
,因为它包含失败的 原因,但您的第一个两个测试没有设置这个值,所以应该只是die "Read or Write symbol not provided";
等另外,
die "Cannot open $file", $!
应该是die qq{Cannot open "$file": $!}
明确文件名是否为空,并在消息和
$!
的值之间添加一些space
从文件中读取的行最后会有一个换行符,所以不需要
say
。只需print while <$fh>
即可Perl 变量名通常是snake_case,所以
get_fh
和do_something
更常见