2013-02-12 16 views
1

我有以下代碼可以刪除我正在使用的文本文件中的行。但是,它實際上並沒有刪除我想要的行。我在這裏做了很多測試,並確認它會刪除行,如果我的行號是正確的。然而,$.似乎是複製實際的行數(當我在上面打印,它說,有雙有行的數量實際上是!)perl Tie ::刪除文本文件中的行

#!/usr/bin/perl 
# find_company_codes.pl 

use strict; 
use warnings; 
use diagnostics; 

use Tie::File; 

my $split_file = "//server/folder/splits_table.txt"; 

# remove fields where only MAS has rollcall 
my @file; 
my @lines; 

tie @file, 'Tie::File', $split_file or die $_; 

foreach (@file) { 

    @lines = split(",",$_); 

    next if $lines[0] eq "ESDB Link Processing Reg-Prd-CCD"; 
    next if $lines[2] ne ""; 
    next if $lines[3] ne ""; 
    next if $lines[4] ne ""; 
    next if $lines[5] ne ""; 
    next if $lines[6] ne ""; 

    splice(@file, $.,1); 

} 

untie @file; 

附: - 我知道我可以使用this,但是,我認爲在這種情況下使用'Tie :: File'會更直接一點。

回答

2

您不是從文件中讀取數據,而是遍歷數組。 $.是沒有意義的。首先,我們需要切換到索引。

for (0..$#file) { 
    my @fields = split(/,/, $file[$_]); 

    next if $fields[0] eq "ESDB Link Processing Reg-Prd-CCD"; 
    next if $fields[2] ne ""; 
    next if $fields[3] ne ""; 
    next if $fields[4] ne ""; 
    next if $fields[5] ne ""; 
    next if $fields[6] ne ""; 

    splice(@file, $_, 1); 
} 

除此之外也不起作用。當你拼接時,你移動整個數組,所以你不能前進轉動的索引,並且你需要儘快完成循環索引。修復:

my $i = 0; 
while ($i < $#file) { 
    my @fields = split(/,/, $file[$i]); 

    if ( $fields[0] ne "ESDB Link Processing Reg-Prd-CCD" 
     && $fields[2] eq "" 
     && $fields[3] eq "" 
     && $fields[4] eq "" 
     && $fields[5] eq "" 
     && $fields[6] eq "" 
    ) { 
     splice(@file, $i, 1); 
    } else { 
     ++$i; 
    } 
} 

好,這有效,但它是瘋狂的慢。每個splice都會導致文件的其餘部分被讀取和重寫。又一個不適當的使用Tie :: File!以下速度將非常快。

use strict; 
use warnings; 

my $qfn = "//rosefs19w/sal..."; 

my @file; 
{ 
    open(my $fh, '<', $qfn) 
     or die("Can't open $qfn: $!\n"); 
    @file = <$fh>; 
} 

my $i = 0; 
while ($i < $#file) { 
    my @fields = split(/,/, $file[$i]); 

    if ( $fields[0] ne "ESDB Link Processing Reg-Prd-CCD" 
     && $fields[2] eq "" 
     && $fields[3] eq "" 
     && $fields[4] eq "" 
     && $fields[5] eq "" 
     && $fields[6] eq "" 
    ) { 
     splice(@file, $i, 1); 
    } else { 
     ++$i; 
    } 
} 

{ 
    open(my $fh, '>', $qfn) 
     or die("Can't create $qfn: $!\n"); 
    print $fh @file; 
} 

沒錯。添加3行額外代碼並刪除2,並且您的代碼變得更快100,1000,10000倍!

+0

感謝您的支持。我正在經歷你剛剛寫下的所有痛苦。我的代碼已經運行了** WAY **太長了。我擔心,並發現困難。再次感謝您的幫助和解釋。 – 2013-02-12 20:43:46

+0

該代碼會將整個文件加載到內存中,但這樣做並不重要,因此它不會更改。 – ikegami 2013-02-12 21:01:21

+0

我不認爲這實際上是通過文件的行。從我所看到的這個'my @fields = split(/,/,$ file [$ _]);'一直引用文件的第一行(標題行)。 – 2013-02-12 21:03:48