Performance 在Perl中从文本文件读入时跳过头的最佳方法?
我从一个用Perl描述的选项卡文件中抓取了几列。文件的第一行与其他行完全不同,因此我希望尽可能快速高效地跳过这一行 这就是我目前所拥有的Performance 在Perl中从文本文件读入时跳过头的最佳方法?,performance,perl,input,io,conditional,Performance,Perl,Input,Io,Conditional,我从一个用Perl描述的选项卡文件中抓取了几列。文件的第一行与其他行完全不同,因此我希望尽可能快速高效地跳过这一行 这就是我目前所拥有的 my $firstLine = 1; while (<INFILE>){ if($firstLine){ $firstLine = 0; } else{ my @columns = split (/\t+/); print OUTFILE "$columns[0]\t\t$c
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";
}
}
my$firstLine=1;
而(){
如果($firstLine){
$firstLine=0;
}
否则{
my@columns=split(/\t+/);
打印输出文件“$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”;
}
}
有没有更好的方法来做到这一点,也许没有$firstLine?或者有没有办法直接从第2行开始读取内嵌
提前谢谢 您可以第一次为其分配一个虚拟变量:
#!/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);
#/usr/bin/perl
严格使用;
使用警告;
打开我的$fh,“可以读取文件句柄中的文件,然后可以使用数组或while循环来迭代行。对于while循环,@Guru为您提供了解决方案。对于阵列,它将如下所示:
#!/usr/bin/perl
use strict;
use warnings;
open (my $fh, '<','a.txt') or die "cant open the file: $! \n";
my @array = <$fh>;
my $dummy = shift (@array); << this is where the headers are stored.
foreach (@array)
{
print $_."\n";
}
close ($fh);
#/usr/bin/perl
严格使用;
使用警告;
打开(我的$fh,我总是使用$。
(当前行号)来实现这一点:
#!/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
}
!/usr/bin/perl
严格使用;
使用警告;
打开我的$fh,“您的代码在以下形式中可能会更优雅:
my $first;
while (...) {
$first++ or next;
# do whatever you want
};
但它仍然很好。@Guru的答案在CPU周期方面更好,但i/o通常比单个if消耗的CPU周期多几个数量级。让我们获取一些数据。我对每个人的技术进行了基准测试
#!/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); },
};
我震惊地发现my@array=
的速度非常慢。考虑到perl解释器中正在进行的所有工作,我本以为这是最快的。然而,它是唯一一个分配内存来容纳所有行的解释器,这可能是性能滞后的原因
使用$。
是另一个惊喜。这可能是访问magic global的成本,也可能是进行数字比较的成本
而且,正如算法分析所预测的,将头检查代码放在循环之外是最快的。但速度不太快。可能不足以担心是否使用下两个最快的头检查代码。我有一个类似的问题。我的解决方案如下-对于解压缩或Gzip文件:
print STDERR "\nReading input file...\n";
if ($file =~ /.gz$/) {
open(IN, "gunzip -c $file | grep -v '##' |") or die " *** ERROR *** Cannot open pipe to [ $file ]!\n";
} else {
open(IN, "cat $file | grep -v '##' |") or die " *** ERROR *** Cannot open [ $file ]!\n";
}
我不知道基准测试,但它对我来说很好
最好的
Sander对我来说,使用拼接似乎是最简单、最干净的方法:
open FILE, "<$ARGV[0]";
my @file = <FILE>;
splice(@file, 0, 1);
openfile”,作为旁注,数组切片和连接将消除大量重复的代码。print OUTFILE“$columns[0]\t\t”;print OUTFILE join(“\t”),@columns[1,2,3,11,12,15,20,21]);print OUTFILE“\n”
我必须研究连接。我是Perl新手。谢谢!稍微整理一下:print OUTFILE“$columns[0]\t\t.join(“\t”,@列[1,2,3,11,12,15,20,21])。\n;
fh不应该有$,因为它是一个文件句柄。但这看起来是最有效的解决方案。谢谢!这是一个词法文件句柄;现在它确实是首选。@JimDavis那些日子已经过去了。作为一种通用技术,它的性能较低,因为您的循环现在必须在每次迭代中进行额外的检查。它也很混乱性能损失是给定的,但由于它看起来更整洁,因此可以忽略不计,值得一试。如果你觉得它在循环中杂乱无章,那一定是味道的问题。“杂乱无章”这意味着它增加了您必须了解的代码量,以了解循环中发生了什么,但它只适用于第一次迭代。我将它与Guru的最佳情况进行比较,即将代码放在循环之外,而不是OP。通过将整个文件存储在数组中,这可能会消耗大量内存。这比比从磁盘顺序读取文件更有效。15年前,“大量内存”很重要。
open FILE, "<$ARGV[0]";
my @file = <FILE>;
splice(@file, 0, 1);