根据排序列表从CSV文件中删除一些行

时间:2014-04-14 18:34:05

标签: perl csv

我有一个包含~175M行(large.csv)的CSV文件和另一个包含~50行(small.csv)的CSV文件。我必须通过large.csv直到找到包含small.csv中第一行的行并删除该行。从那里开始,我需要找到一行包含small.csv中的第二行并删除它,依此类推,直到我到达small.csv的末尾(所有行将按照它们现在的顺序进行匹配)。

这是我能够放在一起但我刚刚收回原始文件:

use strict;
use warnings;

use File::Copy;

my $delete = 'small.csv';
my $file = 'large.csv';
my $backup = "$file.bak";
copy $file, $backup or die "Copy failed: $!";

open my $in_dh, '<', $delete or die "$delete: $!";
open my $in_fh, '<', $backup or die "$backup: $!";
open my $out_fh, '>', $file or die "$file: $!";

my $match = <$in_dh>;
while (my $line = <$in_fh>) {
    if (index ($line, $match) == -1) {
        print $out_fh $line;
    } else {
        $match = <$in_dh>;
    }
}

close $in_dh;
close $in_fh;
close $out_fh;

1 个答案:

答案 0 :(得分:1)

你不要chomp$match结尾的行,所以除非匹配在一行的末尾,否则它将会失败。在阅读small.csv时,您也不会检查是否点击了EOF。

由于您的第一个文件较小,因此最简单的方法是将其加载到数组中。以下程序执行此操作,并使用$^I<>来处理文件的就地编辑:

use strict;
use warnings;
use 5.010;

my @needles;
while (<>) {
    chomp;
    push @needles, $_;
    last if eof;
}

{
    local $^I = '.bak';

    my $needle = shift @needles;
    while (<>) {
        chomp;

        if (! defined $needle or index($_, $needle) == -1) {
            say;
        }
        else {
            $needle = shift @needles;
        }
    }
}

这样称呼:

/path/to/script needles haystack

其中needles是包含要搜索的字符串的文件,haystack是要搜索的文件。