Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何读取作为数组元素的Perl文件句柄?_Perl_Arrays_Filehandle - Fatal编程技术网

如何读取作为数组元素的Perl文件句柄?

如何读取作为数组元素的Perl文件句柄?,perl,arrays,filehandle,Perl,Arrays,Filehandle,我很快草草记下了一个Perl脚本,该脚本将几个文件平均起来,只包含一列数字。它涉及从文件句柄数组中读取。以下是脚本: #!/usr/local/bin/perl use strict; use warnings; use Symbol; die "Usage: $0 file1 [file2 ...]\n" unless scalar(@ARGV); my @fhs; foreach(@ARGV){ my $fh = gensym; open $fh, $_ or di

我很快草草记下了一个Perl脚本,该脚本将几个文件平均起来,只包含一列数字。它涉及从文件句柄数组中读取。以下是脚本:

#!/usr/local/bin/perl

use strict;
use warnings;

use Symbol;

die "Usage: $0 file1 [file2 ...]\n" unless scalar(@ARGV);

my @fhs;

foreach(@ARGV){
    my $fh = gensym;
    open $fh, $_ or die "Unable to open \"$_\"";
    push(@fhs, $fh);
}

while (scalar(@fhs)){
    my ($result, $n, $a, $i) = (0,0,0,0);
    while ($i <= $#fhs){
        if ($a = <$fhs[$i]>){
            $result += $a;
            $n++;
            $i++;
        }
        else{
            $fhs[$i]->close;
            splice(@fhs,$i,1);
        }
    }
    if ($n){ print $result/$n . "\n"; }
}
#/usr/local/bin/perl
严格使用;
使用警告;
使用符号;
die“用法:$0 file1[file2…]\n”,除非标量(@ARGV);
我的@fhs;
foreach(@ARGV){
my$fh=gensym;
打开$fh、$或死“无法打开\“$”;
推送(@fhs,$fh);
}
while(标量(@fhs)){
我的($result,$n,$a,$i)=(0,0,0,0);
当我关门的时候;
拼接(@fhs,$i,1);
}
}
如果($n){print$result/$n.“\n”;}
}
这不起作用。如果我调试脚本,在初始化@fhs之后,它看起来如下所示:

  DB<1> x @fhs
0  GLOB(0x10443d80)
   -> *Symbol::GEN0
         FileHandle({*Symbol::GEN0}) => fileno(6)
1  GLOB(0x10443e60)
   -> *Symbol::GEN1
         FileHandle({*Symbol::GEN1}) => fileno(7)
DB x@fhs
0全局(0x10443d80)
->*符号::GEN0
FileHandle({*Symbol::GEN0})=>fileno(6)
1全局(0x10443e60)
->*符号::GEN1
FileHandle({*Symbol::GEN1})=>fileno(7)
到目前为止,还不错。但在我尝试读取文件的部分失败:

  DB<3> x $fhs[$i]
0  GLOB(0x10443d80)
   -> *Symbol::GEN0
         FileHandle({*Symbol::GEN0}) => fileno(6)
  DB<4> x $a
0  'GLOB(0x10443d80)'
DB x$fhs[$i]
0全局(0x10443d80)
->*符号::GEN0
FileHandle({*Symbol::GEN0})=>fileno(6)
DB x$a
0'全局(0x10443d80)'

$a是用这个字符串填充的,而不是从全局读取的内容。我做错了什么?

您只能在
中使用一个简单的标量变量来读取文件句柄。
可以工作。
不从文件句柄读取;它实际上相当于
glob($foo[0])
。您必须使用
readline
内置的临时变量,或者使用and和OO表示法

$text = readline($foo[0]);
# or
my $fh = $foo[0];  $text = <$fh>;
# or
$text = $foo[0]->getline;  # If using IO::File
$text=readline($foo[0]);
#或
my$fh=$foo[0];$text=;
#或
$text=$foo[0]->getline;#如果使用IO::File
如果没有从循环内的数组中删除元素,可以通过将
while
循环更改为
foreach
循环来轻松使用临时变量


就我个人而言,我认为使用
gensym
创建文件句柄是一个难看的黑客行为。您应该使用IO::File,或者将一个未定义的变量传递给
open
(这至少需要Perl 5.6.0,但现在已经快10年了)。(只需说
my$fh;
而不是
my$fh=gensym;
,当您调用
open
时,Perl将自动创建一个新的文件句柄并将其存储在
$fh
中)

我理解您的逻辑有困难。是否要读取几个只包含数字(每行一个数字)的文件然后打印平均值

use strict;
use warnings;

my @fh;
foreach my $f (@ARGV) {
    open(my $fh, '<', $f) or die "Cannot open $f: $!";
    push @fh, $fh;
}

foreach my $fh (@fh) {
    my ($sum, $n) = (0, 0);
    while (<$fh>) {
        $sum += $_;
        $n++;
    }
    print "$sum / $n: ", $sum / $n, "\n" if $n;
}
使用严格;
使用警告;
我的@fh;
每个我的$f(@ARGV){

打开(我的$fh,“如果你愿意使用一些魔法,你可以非常简单地做到这一点:

use strict;
use warnings;

die "Usage: $0 file1 [file2 ...]\n" unless @ARGV;

my $sum   = 0;

# The current filehandle is aliased to ARGV
while (<>) {
    $sum += $_;
} 
continue {
    # We have finished a file:
    if( eof ARGV ) {
        # $. is the current line number.
        print $sum/$. , "\n" if $.;
        $sum = 0;

        # Closing ARGV resets $. because ARGV is 
        # implicitly reopened for the next file.
        close ARGV;  
    }
}
使用严格;
使用警告;
die“用法:$0 file1[file2…]\n”,除非@ARGV;
我的$sum=0;
#当前文件句柄的别名为ARGV
而(){
$sum+=$\ux;
} 
继续{
#我们已完成一个文件:
如果(eof ARGV){
#$。是当前行号。
打印$sum/$,如果$,则为“\n”。;
$sum=0;
#关闭ARGV将重置$。因为ARGV是
#隐式地为下一个文件重新打开。
关闭ARGV;
}
}

除非您使用的是非常旧的perl,否则没有必要乱搞
gensym
。IIRC、perl 5.6和更新版本对正常的词法句柄很满意:
open my$fh,似乎是
for
循环对您更有效,因为您可以实际使用标准的读取(迭代)操作符

for my $fh ( @fhs ) { 
    while ( defined( my $line = <$fh> )) {
        # since we're reading integers we test for *defined*
        # so we don't close the file on '0'
        #...
    }
    close $fh;
}
我的$fh(@fhs){
while(已定义(my$line=)){
#因为我们读取的是整数,所以我们测试的是*定义的*
#因此我们不关闭“0”上的文件
#...
}
收盘价$fh;
}

看起来你根本不想缩短循环。因此,
while
似乎是一个错误的循环习惯用法。

我会给你1000个停止使用p的代表。问题是文件不能保证有相同的行数。或者等同于
,它被拼写为
readline HANDLE
ike.但是,
$count
有什么用呢?另外,
除非在标量上下文中隐式使用
@ARGV
,我不会把它算作魔法,我也会这样写:)好的方面。除非标量是粘贴OP代码时留下的。$计数是在我意识到我可以使用行号之前留下的。