从Perl中的文本文件读入时跳过标题的最佳方法是什么?

New*_*erl 8 io perl performance conditional input

我从Perl中的tab标签文件中抓取了一些列.该文件的第一行与其他行完全不同,因此我想尽可能快速有效地跳过该行.

这就是我到目前为止所拥有的.

my $firstLine = 1;

while (<INFILE>){
    if($firstLine){
        $firstLine = 0;
    }
    else{
        my @columns = split (/\t+/);
        print OUTFILE "$columns[0]\t\t$columns[1]\t$columns[2]\t$columns[3]\t$columns[11]\t$columns[12]\t$columns[15]\t$columns[20]\t$columns[21]\n";
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来做到这一点,也许没有$ firstLine?或者有没有办法直接从第2行开始阅读INFILE?

提前致谢!

Sch*_*ern 29

让我们得到一些数据.我对每个人的技术进行了基准测试......

#!/usr/bin/env perl

sub flag_in_loop {
    my $file = shift;

    open my $fh, $file;

    my $first = 1;
    while(<$fh>) {
        if( $first ) {
            $first = 0;
        }
        else {
            my $line = $_;
        }
    }

    return;
}

sub strip_before_loop {
    my $file = shift;

    open my $fh, $file;

    my $header = <$fh>;
    while(<$fh>) {
        my $line = $_;
    }

    return;
}

sub line_number_in_loop {
    my $file = shift;

    open my $fh, $file;

    while(<$fh>) {
        next if $. < 2;

        my $line = $_;
    }

    return;
}

sub inc_in_loop {
    my $file = shift;

    open my $fh, $file;

    my $first;
    while(<$fh>) {
        $first++ or next;

        my $line = $_;
    }

    return;
}

sub slurp_to_array {
    my $file = shift;

    open my $fh, $file;

    my @array = <$fh>;
    shift @array;

    return;
}


my $Test_File = "/usr/share/dict/words";
print `wc $Test_File`;

use Benchmark;

timethese shift || -10, {
    flag_in_loop        => sub { flag_in_loop($Test_File); },
    strip_before_loop   => sub { strip_before_loop($Test_File); },
    line_number_in_loop => sub { line_number_in_loop($Test_File); },
    inc_in_loop         => sub { inc_in_loop($Test_File); },
    slurp_to_array      => sub { slurp_to_array($Test_File); },
};
Run Code Online (Sandbox Code Playgroud)

由于这是I/O,可能受到Benchmark.pm调整能力的影响,我跑了几次并检查我得到了相同的结果.

/usr/share/dict/words是一个2.4兆字节的文件,有大约240k非常短的行.由于我们没有处理线路,因此线路长度无关紧要.

我只在每个例程中做了很少的工作来强调技术之间的差异.我想做一些工作,以便通过改变你阅读文件的方式,为你将获得或失去的性能产生一个现实的上限.

我是在带有SSD的笔记本电脑上做到这一点,但它仍然是笔记本电脑.随着I/O速度的增加,CPU时间变得更加重要.在具有快速I/O的机器上,技术更为重要.

这是每个例程每秒读取文件的次数.

slurp_to_array:       4.5/s
line_number_in_loop: 13.0/s
inc_in_loop:         15.5/s
flag_in_loop:        15.8/s
strip_before_loop:   19.9/s
Run Code Online (Sandbox Code Playgroud)

我很震惊地发现这my @array = <$fh>是一个很大的差距.考虑到perl解释器中发生的所有工作,我本以为它会是最快的.但是,它是唯一一个分配内存来容纳所有行的人,这可能是性能滞后的原因.

使用$.是另一个惊喜.也许这是访问魔术全球的成本,或者可能是它进行数字比较.

并且,正如算法分析所预测的那样,将头部校验码放在循环之外是最快的.但不是很多.可能还不足以担心你是否正在使用下两个最快的.


Gur*_*uru 20

您可以第一次为它分配一个虚拟变量:

#!/usr/bin/perl
use strict;
use warnings;

open my $fh, '<','a.txt' or die $!;

my $dummy=<$fh>;   #First line is read here
while(<$fh>){
        print ;
}
close($fh);
Run Code Online (Sandbox Code Playgroud)

  • 这是一个词法文件句柄; 这些天实际上是首选. (3认同)

fle*_*esk 7

我总是使用$.(当前行号)来实现这个目的:

#!/usr/bin/perl
use strict;
use warnings;

open my $fh, '<', 'myfile.txt' or die "$!\n";

while (<$fh>) {
    next if $. < 2; # Skip first line

    # Do stuff with subsequent lines
}
Run Code Online (Sandbox Code Playgroud)