从文件中有效删除包含字符串的文件中的行

时间:2014-03-18 23:58:18

标签: python perl bash unix

FileA包含行 FileB包含单词

如何有效从包含在FileA中找到的字词的FileB中删除行?

我尝试了以下操作,我甚至不确定它们是否有效,因为它需要很长时间才能运行。

尝试grep

grep -v -f <(awk '{print $1}' FileB.txt) FileA.txt > out

还尝试python

f = open(sys.argv[1],'r')
out = open(sys.argv[2], 'w')
bad_words = f.read().splitlines()

with open('FileA') as master_lines:
  for line in master_lines:
    if not any(bad_word in line for bad_word in bad_words):
      out.write(line)

FILEA:

abadan refinery is one of the largest in the world.
a bad apple spoils the barrel.
abaiara is a city in the south region of brazil.
a ban has been imposed on the use of faxes

FILEB:

abadan
abaiara

期望的输出:

a bad apple spoils the barrel.
a ban has been imposed on the use of faxes

3 个答案:

答案 0 :(得分:2)

我拒绝相信Python至少不能与Perl的性能相匹配。这是我在Python中解决此问题的更有效版本的快速尝试。我正在使用sets来优化此问题的搜索部分。 &amp; operator返回一个新集合,其中包含两个集合共有的元素。

这个解决方案在我的机器上运行需要12秒才能获得带有3M行的fileA和带有200k单词的fileB,而perl需要9秒。最大的减速似乎是re.split,这似乎比字符串更快。在这种情况下分裂。

如果您有任何改善速度的建议,请对此答案发表评论。

import re

filea = open('Downloads/fileA.txt')
fileb = open('Downloads/fileB.txt')

output = open('output.txt', 'w')
bad_words = set(line.strip() for line in fileb)

splitter = re.compile("\s")
for line in filea:
    line_words = set(splitter.split(line))
    if bad_words.isdisjoint(line_words):
        output.write(line)

output.close()

答案 1 :(得分:1)

你看起来很好的命令可能是时候尝试一种好的脚本语言了。尝试运行以下perl脚本,看看它是否更快地报告回来。

#!/usr/bin/perl

#use strict;
#use warnings;

open my $LOOKUP, "<", "fileA" or die "Cannot open lookup file: $!";
open my $MASTER, "<", "fileB" or die "Cannot open Master file: $!";
open my $OUTPUT, ">", "out" or die "Cannot create Output file: $!";

my %words;
my @l;

while (my $word = <$LOOKUP>) {
    chomp($word);
    ++$words{$word};
}

LOOP_FILE_B: while (my $line = <$MASTER>) {
    @l = split /\s+/, $line;
        for my $i (0 .. $#l) {
            if (defined $words{$l[$i]}) {
                next LOOP_FILE_B;
            }
        }
    print $OUTPUT "$line"
}

答案 2 :(得分:1)

使用grep

grep -v -Fwf fileB fileA