1

我想从 <> 读取 100 KB,对此进行一些测试,然后将 100 KB 放回去,以便稍后由 <> 读取它们。

在元代码中:

$data100kb = read(<>,100000);
testing($data100kb);
unget(<>,$data100kb);
while(<>) {
  do stuff;
}

我事先不知道 <> 是否会为我提供实际文件、管道或实际文件的串联。所以它应该与:

cat bigfile_a bigfile_b | perl my_program

假设大文件是 1000*RAM 大小,因此复制输入的成本非常高。

如果我只能从 STDIN 读取,这是可以接受的。

背景

前 100kb 告诉我如何解析完整的输入,但解析器也需要这个输入。

4

3 回答 3

1

这似乎适用于 STDIN。如果它可以更快地完成,那就太好了。

read(STDIN, $first, 100000);
unget($first);

compute($first);

while($_=get_line()) {
    # Similar to while(<>)
}

my @line_cache;
sub get_line {
    if(@line_cache) {
        my $line = shift @line_cache;
        if(@line_cache) {
            # not last line                                                                                                            
            return $line;
        } else {
            # last line - may be incomplete                                                                                            
            if(substr($line, -1, 1) eq $/) {
                # Line is complete                                                                                                     
                return $line;
            } else {
                return $line. scalar(<STDIN>);
            }
        }
    } else {
        return scalar(<STDIN>);
    }
}

sub unget {
    for(@_) {
        # Split into lines                                                                                                             
        push @line_cache, split m:(?<=$/):;
    }
}
于 2013-10-14T11:28:41.893 回答
1

为了后代......我写了 FileHandle::Unget 来解决这个问题。

于 2018-07-02T02:39:48.273 回答
0

我不知道这是否满足您的需求。如果你坚持使用 <>,那么我猜你必须使用tie.

#copy STDIN to another filehandle: $fh
my $fakefile = join '', <STDIN>;
open my $fh, '<', \$fakefile;

#read 100kb
read $fh, my $data100kb, 100_000;

#do something with the data
#$data100kb =~ y/a/b/;
#print $data100kb;

#reset $fh
seek $fh, 0, 0;

while(<$fh>){
    print;# do some stuff
}
于 2013-10-14T10:23:51.750 回答